この記事は編集レビューを必要としています。ぜひご協力ください。
この記事は翻訳作業中です。
警告: オブジェクトの[[Prototype]]
を変更することは、最新のJavaScriptエンジンがプロパティアクセスを最適化する仕組み上、すべてのブラウザやJavaScriptエンジンにおいて、とても低速な操作となります。プロトタイプの継承関係を変更することによる性能上の影響は微細で広範囲にわたり、単にobj.__proto__ = ...
という文の実行時間に留まらず、[[Prototype]]が変更された
いずれかのオブジェクトへのアクセスを持つあらゆるコードに及ぶかもしれません。性能を気にしている場合、オブジェクトの[[Prototype]]
の変更は避けるべきです。かわりに、Object.create()
を使用して望み通りの[[Prototype]]
をもつオブジェクトを新たに生成してください。
警告: Object.prototype.__proto__
は現時点でほとんどのブラウザがサポートしていますが、そのプロパティの存在と正確な動作は、ウェブブラウザーの互換性を確保するためのレガシー機能として、ECMAScript 6で初めて標準化されました。かわりにObject.getPrototypeOf()
だけを使用することが推奨されます。
概要
Object.prototype
の__proto__
プロパティは、アクセスされるオブジェクトの内部の[[Prototype]]
(オブジェクトまたはnull
のどちらか)を暴露するアクセサプロパティ(getter関数とsetter関数)です。
__proto__
の使用は、論争の的になり、推奨されていません。EcmaScript言語仕様にもともとは含まれていませんでした。しかし、最新のブラウザはとにかくそれを実装することを決定しました。今日、__proto__
プロパティはECMAScript第6版言語仕様で標準化されました。そして、将来にサポートされます。それにもかかわらず、オブジェクトの[[Prototype]]
を変化させることは、性能を気にしている場合避けるべき低速の操作です。
__proto__
プロパティは、生成時に[[Prototype]]
オブジェクトを設定するためにObject.create()
のかわりとしてオブジェクトリテラルの定義で使用されます。参照: object initializer / literal syntax
構文
var shape = {}, circle = new Circle(); // Set the object prototype shape.__proto__ = circle; // Get the object prototype console.log(shape.__proto__ === circle); // true
注意: それは、2つのアンダースコアがあり、5文字"proto"が続いて、さらに2つのアンダースコアが続きます。
説明
__proto__
getter 関数はオブジェクトの内部の[[Prototype]]
の値を外部にさらします。オブジェクトリテラルを使用して生成されたオブジェクトに対して、この値はObject.prototype
です。配列リテラルを使用して生成されたオブジェクトに対して、この値はArray.prototype
です。関数に対して、この値はFunction.prototype
です。new fun
を使用して生成されたオブジェクトの対して、この値はfun.prototype
です。ここで、fun
はJavaScript (Array
、Boolean
、Date
、 Number
、 Object
、 String
等 —JavaScriptの進化として追加された新しいコンストラクタを含みます。)によって提供されるビルトインコンストラクタ関数の一つです。new fun
を使用して生成されたオブジェクトに対して、この値は常にfun.prototype
の値です。ここで、fun
はスクリプトで定義された関数です。(すなわち、新しい値がfun.prototype
に割り当てられている場合、以前生成されたfun
インスタンスも[[Prototype]]
として新しい値を持ち、__proto__とfun.prototype
として同じアドレスを参照します)。
__proto__
setterでオブジェクトの[[Prototype]]
は変化することができます。オブジェクトは、Object.isExtensible()
に応じて拡張可能である必要があります。: 拡張可能ではない場合、TypeError
がスローされます。与えられた値がオブジェクト、または、null
である必要があります。他の値を提供することは何もしません。
プロトタイプが継承のためにどのように使用されるかを理解するには、ガイド記事Inheritance and the prototype chainを参照してください。
__proto__
プロパティは、getter関数とsetter関数からなるObject.prototype
上の簡単なアクセスプロパティです。最終的にのObject.prototype
を参照する__proto__
に対してのプロパティアクセスはこのプロパティを探します。しかし、Object.prototype
を参照しないアクセスはこのプロパティを探しません。Object.prototype
が参照される前にいくつかの他の__proto__
プロパティが見つけられた場合、そのプロパティは、Object.prototype
上で見つけられたプロパティを隠します。
var noProto = Object.create(null); console.log(typeof noProto.__proto__); // undefined console.log(Object.getPrototypeOf(noProto)); // null noProto.__proto__ = 17; console.log(noProto.__proto__); // 17 console.log(Object.getPrototypeOf(noProto)); // null var protoHidden = {}; Object.defineProperty(protoHidden, "__proto__", { value: 42, writable: true, configurable: true, enumerable: true }); console.log(protoHidden.__proto__); // 42 console.log(Object.getPrototypeOf(protoHidden) === Object.prototype); // true
例
次の例では、Employee
の新しいインスタンスが生成され、__proto__
がコンストラクタのprototype
と同じであることを示すためにテストを実施します。
// Declare a function to be used as a constructor function Employee() { /* initialise instance */ } // Create a new instance of Employee var fred = new Employee(); // Test equivalence fred.__proto__ === Employee.prototype; // true
この時点で、fred
はEmployee
から継承します。しかしながら、違うオブジェクトをfred.__proto__
を割り当てることで変更できます。:
function Cow() { /* initialise instance */ } // Assign a new object to __proto__ fred.__proto__ = Cow.prototype;
今 fred
はEmployee.prototype
のかわりにCow.prototype
から直接継承します。Employee.prototype
から元来継承されたプロパティを失います。
しかしながら、これは、extensibleオブジェクトに適用するのみで、拡張不可なオブジェクトの__proto__
プロパティは変更されません。:
var obj = {}; Object.preventExtensions(obj); obj.__proto__ = {}; // throws a TypeError
Object.prototype
の__proto__
プロパティでさえ、連鎖がnullに続く限り再定義されることに注意して下さい。:
var b = {}; Object.prototype.__proto__ = Object.create(null, // [[Prototype]] { hi: { value: function() { alert('hi'); } } }); b.hi();
Object.prototype
の__proto__
が、null
に設定されない場合、または、プロトタイプチェーンが最終的に明示的にはnull
につながらない別のオブジェクトに設定されない場合、チェーンが最終的にnull
につながるので、"cyclic __proto__ value" TypeError
がスローされます。 (それは通常どおりObject.prototype
上です)。
仕様
仕様 | 状況 | コメント |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) Object.prototype.__proto__ の定義 |
標準 | Webブラウザのために追加ECMAScript機能の(規定)附属書に含まれています(仕様が既に実装されているものを体系化することに注意してください)。 |
ブラウザ実装状況
注意: ES6の仕様が、__proto__
へのサポートがWebブラウザに必要であることを規定している間、(規範として奨励されていますが)他の環境では必要ではありません。コードがWebブラウザではない環境をサポートする必要がある場合、かわりに、Object.getPrototypeOf()
とObject.setPrototypeOf()
を使用することが推奨されています。
機能 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
基本サポート | (有) | (有) | 11 | (有) | (有) |
機能 | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
基本サポート | (有) | (有) | (有) | (有) | (有) | (有) |