JavaScriptにおける[[Prototype]]とプロトタイプの関係
-
23-08-2019 - |
質問
から http://www.jibbering.com/faq/faq_notes/closures.html :
注記:ECMAScript は、内部オブジェクト タイプの内部 [[prototype]] プロパティを定義します。このプロパティはスクリプトから直接アクセスできませんが、プロパティ アクセサーの解決に使用される内部 [[prototype]] プロパティで参照されるオブジェクトのチェーンです。オブジェクトのプロトタイプチェーン。パブリック プロトタイプ プロパティは、内部 [[prototype]] プロパティと関連付けてプロトタイプの割り当て、定義、操作を可能にするために存在します。 2 つの間の関係の詳細は ECMA 262 (第 3 版) に記載されており、この説明の範囲を超えています。
二人の関係の詳細はどうなっているのでしょうか?ECMA 262 を閲覧しましたが、次のような内容しか読み取れませんでした。
コンストラクターに関連付けられたプロトタイプは、プログラム式constructor.prototypeによって参照できます。
ネイティブ ECMAScript オブジェクトには、[[Prototype]] と呼ばれる内部プロパティがあります。このプロパティの値は null またはオブジェクトのいずれかで、継承の実装に使用されます。
すべての組み込み関数とすべての組み込みコンストラクターには、式 Function.prototype の初期値である Function プロトタイプ オブジェクトがあります。
すべての内蔵プロトタイプオブジェクトには、オブジェクトプロトタイプオブジェクト自体を除き、内部[[プロトタイプ]]プロパティの値として、式オブジェクトの初期値(15.3.2.1)の式の初期値であるオブジェクトプロトタイプオブジェクトがあります。
このことから私が収集したのは、[[Prototype]] プロパティが prototype
ほとんどすべてのオブジェクトのプロパティ。私が間違っているでしょうか?
解決
私はあなたがほとんどの場合、正しいと信じています。
すべてのオブジェクトは、継承のために使用されている隠された[[Prototype]]
プロパティを持っています。機能が付加機能をコンストラクタとして使用される場合にのみ使用されるパブリックprototype
性を有する:オブジェクトがnew
を用いて構成されている場合、新たなオブジェクトの[[Prototype]]
プロパティはコンストラクタとして使用された関数のprototype
プロパティに設定されています。
例えばます。
function C() {}
C.prototype = P1;
var obj = new C(); // obj.[[Prototype]] is now P1.
あなたは[[Prototype]]
を使用してObject.getPrototypeOf(<obj>)
プロパティを取得することができます。 (このメソッドは、JavaScriptの古いバージョンのは[[Prototype]]
を読んで、任意の標準的な方法を持っていないのECMAScript 5で指定されている)。
あなたはの通常の例えば、コンストラクタで試作品を得ることができます:ます。
obj.constructor.prototype == Object.getPrototypeOf(obj)
しかし、コンストラクタ関数のprototypeプロパティを再割り当てすることができますので、これは、必ずしもそうではありませんが、オブジェクトが作成された後のオブジェクトの[[Prototype]]
を再割り当てすることはできません。だから、あなたが行う場合:
C.prototype = P2;
そして
obj.constructor.prototype != Object.getPrototypeOf(obj)
C
のプロトタイプは今P2
ですが、[[Prototype]]
のobj
はまだP1
ですので。
それはprototype
プロパティを持っているののみの関数であることに注意してください。機能のprototype
プロパティは機能の[[Prototype]]
プロパティと同じではないことにも注意してください!
他のヒント
質問に直接答えるには:論理的には、それはオブジェクトのプライベートコピーです。 prototype
コンストラクターのプロパティ。メタ言語を使用すると、オブジェクトは次のように作成されます。
// not real JS
var Ctr = function(...){...};
Ctr.prototype = {...}; // some object with methods and properties
// the object creation sequence: var x = new Ctr(a, b, c);
var x = {};
x["[[prototype]]"] = Ctr.prototype;
var result = Ctr.call(x, a, b, c);
if(typeof result == "object"){ x = result; }
// our x is fully constructed and initialized at this point
この時点で、プロトタイプを変更できます。クラスのすべてのオブジェクトはプロトタイプを参照によって参照するため、その変更はクラスのすべてのオブジェクトに反映されます。
Ctr.prototype.log = function(){ console.log("...logging..."); };
x.log(); // ...logging..
しかし、コンストラクターのプロトタイプを変更すると、すでに作成されたオブジェクトは古いオブジェクトを参照し続けることになります。
Ctr.prototype = {life: 42};
// let's assume that the old prototype didn't define "life"
console.log(x.life); // undefined
x.log(); // ...logging...
規格に完全に準拠 [[prototype]]
は利用できませんが、Mozilla は標準を次のように拡張しています。 __proto__
プロパティ (読み取り専用)。通常は非表示になっているプロパティを公開します。 [[prototype]]
:
また、 __proto__
で合法化できる 次期ES3.1規格.
olavkの回答に加えて:いくつかのJavaScriptの実装(例えば Mozillaの)にアクセスすることを可能にする[[プロトタイプ]]プロパティを直接...