aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/javascript/reference/global_objects/object/proto/index.md
blob: e7ad3390d942cc7fe23145c4f9d6d6aa7ca31aee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
---
title: Object.prototype.__proto__
slug: Web/JavaScript/Reference/Global_Objects/Object/proto
tags:
  - Deprecated
  - ECMAScript 2015
  - JavaScript
  - Object
  - Property
  - Prototype
  - Reference
browser-compat: javascript.builtins.Object.proto
translation_of: Web/JavaScript/Reference/Global_Objects/Object/proto
---
{{JSRef}}{{Deprecated_header}}

> **Warning:** オブジェクトの `[[Prototype]]` を変更することは、最新の JavaScript エンジンがプロパティアクセスを最適化する仕組み上、***すべての***ブラウザーや JavaScript エンジンにおいて、とても低速な操作となります。プロトタイプの継承関係を変更することによる性能上の影響は微細で広範囲にわたり、単に `obj.__proto__ = ...` という文の実行時間に留まらず、 `[[Prototype]]` が変更された***いずれかの***オブジェクトへのアクセスを持つ***あらゆる***コードに及ぶ可能性があります。性能を気にしている場合、オブジェクトの `[[Prototype]]` の変更は避けるべきです。代わりに、 {{JSxRef("Object.create()")}} を使用して求める `[[Prototype]]` をもつオブジェクトを新たに生成してください。

> **Warning:** `Object.prototype.__proto__` は現時点でほとんどのブラウザーが対応していますが、そのプロパティの存在と正確な動作は、ウェブブラウザーの互換性を確保するためのレガシー機能として、 ECMAScript 2015 で初めて標準化されました。より広く対応させるには、代わりに {{JSxRef("Object.getPrototypeOf()")}} を使用してください。

`__proto__` は {{JSxRef("Object.prototype")}} のアクセサープロパティ (ゲッター関数およびセッター関数) で、アクセスされるオブジェクトの内部の `[[Prototype]]` (オブジェクトまたは {{JSxRef("Global_Objects/null", "null")}} のどちらか) を暴露します。

`__proto__` の使用は、論争の的になり、推奨されていません。もともと ECMAScript 言語仕様には含まれていませんでしたが、現在のブラウザーでは結局それを実装しています。最近になって、 `__proto__` プロパティはウェブブラウザー間の互換性を保つために ECMAScript2015 の仕様で標準化されたので、将来的には対応されることになります。これは非推奨扱いで、代わりに {{JSxRef("Object.getPrototypeOf")}}/{{JSxRef("Reflect.getPrototypeOf")}} および {{JSxRef("Object.setPrototypeOf")}}/{{JSxRef("Reflect.setPrototypeOf")}} を推奨しています (とはいえ、オブジェクトの `[[Prototype]]` の設定は、性能が気になる場合には避けるべき低速の操作ですが)。

また、 `__proto__` プロパティは、生成時に `[[Prototype]]` オブジェクトを設定するために {{JSxRef("Object.create()")}} の代わりとしてもオブジェクトリテラルの定義で使用されます。参照: [オブジェクト初期化子 / リテラル構文](/ja/docs/Web/JavaScript/Reference/Operators/Object_initializer)

## 解説

`__proto__` ゲッター関数はオブジェクトの内部の `[[Prototype]]` の値を外部に公開します。オブジェクトリテラルを使用して生成されたオブジェクトでは、この値は {{JSxRef("Object.prototype")}} です。配列リテラルを使用して生成されたオブジェクトでは、この値は {{JSxRef("Array.prototype")}} です。関数では、この値は {{JSxRef("Function.prototype")}} です。 `new fun` を使用して生成されたオブジェクトでは、 `fun` が JavaScript の ({{JSxRef("Array")}}、{{JSxRef("Boolean")}}、{{JSxRef("Date")}}、 {{JSxRef("Number")}}、 {{JSxRef("Object")}}、 {{JSxRef("String")}} などによって提供された内蔵コンストラクター関数のうちの一つである場合は — JavaScript の進化によって追加された新しいコンストラクタを含みます)、この値は常に `fun.prototype` です。 `new fun` を使用して生成されたオブジェクトでは、 `fun` がスクリプトで定義された関数である場合、この値は常に `fun.prototype` の値です。 (すなわち、コンストラクターがほかのオブジェクトを明示的に返さない場合、または `fun.prototype` に再代入されていない場合)。

`__proto__` のセッターでオブジェクトの `[[Prototype]]` を変更することができます。オブジェクトは、 {{JSxRef("Object.isExtensible()")}} に応じて拡張可能である必要があります。拡張可能ではない場合、 {{JSxRef("Global_Objects/TypeError", "TypeError")}} が発生します。与えられた値はオブジェクト、または {{JSxRef("Global_Objects/null", "null")}} である必要があります。他の値が与えられた場合は何もしません。

プロトタイプが継承のためにどのように使用されるかを理解するには、ガイド記事の[継承とプロトタイプチェーン](/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)を参照してください。

`__proto__` プロパティは、ゲッター関数とセッター関数からなる {{JSxRef("Object")}} 上の簡単なアクセサープロパティです。最終的にの {{JSxRef("Object")}} を参照する `__proto__` に対してのプロパティアクセスはこのプロパティを探します。しかし、 {{JSxRef("Object")}} を参照しないアクセスはこのプロパティを探しません。 {{JSxRef("Object")}} が参照される前にいくつかの他の `__proto__` プロパティが見つけられた場合、そのプロパティは、 {{JSxRef("Object")}} 上で見つけられたプロパティを隠します。

## 例

### \_\_proto\_\_ の使用

```js

function Circle() {}
const shape = {};
const circle = new Circle();

// オブジェクトプロトタイプの設定
// 非推奨。 参考用です。 実際のコードで使用しないでください。
shape.__proto__ = circle;

// オブジェクトプロトタイプの取得
console.log(shape.__proto__ === Circle);  // false

const ShapeA = function () {};
const ShapeB = {
    a() {
        console.log('aaa');
    }
};
console.log(ShapeA.prototype.__proto__ = ShapeB);

const shapea = new ShapeA();
shapea.a(); // aaa
console.log(ShapeA.prototype === shapea.__proto__); // true

// または
const ShapeC = function () {};
const ShapeD = {
    a() {
        console.log('a');
    }
};

const shapeC = new ShapeC();
shapeC.__proto__ = ShapeD;
shapeC.a(); // a
console.log(ShapeC.prototype === shapeC.__proto__); // false

// または
function Test() {}
Test.prototype.myname = function () {
    console.log('myname');
};

const a = new Test();
console.log(a.__proto__ === Test.prototype); // true
a.myname(); // myname

// または
const fn = function () {};
fn.prototype.myname = function () {
    console.log('myname');
};

var obj = {
    __proto__: fn.prototype
};

obj.myname(); // myname

 
```

## 仕様書

{{Specifications}}

## ブラウザーの互換性

{{Compat}}

## 関連情報

- {{JSxRef("Object.prototype.isPrototypeOf()")}}
- {{JSxRef("Object.getPrototypeOf()")}}
- {{JSxRef("Object.setPrototypeOf()")}}