注:まず、__proto__
非標準Object.getPrototypeOf
です。短くするために を使用します。私は怠け者なのでprototype
、この回答ではかなりの回数使用しました
私があなたを正しく読んでいるなら、あなたはあなたの最初の仮定に投げ出されています:
Foo.prototype -> Foo{}
(コンストラクターである)のプロトタイプFoo
は、定義上、 のインスタンスですFoo
。ただし、コンストラクターは関数であり、コンストラクターは特定のインスタンスのオブジェクトを返すため、プロトタイプはObject
どちらの方法でも拡張されます。
私はプロトタイプの慣性を従来の OOP と比較するのは好きではありませんが、次のように考えてください。
プロトタイプは一種のFoo
可変クラス定義であり (メソッドとプロパティを随時追加できます)、コンストラクターはこのプロトタイプを拡張するオブジェクトを作成し、インスタンス レベルでプロパティ/メソッドの別のレイヤーを追加します。
したがってFoo.prototype instanceof Foo
、真です。しかし、Foo
オブジェクトであること:
Object.getPrototypeOf(Foo.prototype) === Object.prototype
本当です。同じように
Object.getPrototypeOf(Array.prototype) === Object.prototype.
これを JS (プロトタイプ) 言語に翻訳すると、次のようになります。
JS が作成する関数オブジェクトごとに、このオブジェクトにprototype
プロパティが割り当てられます。プロパティはのprototype
インスタンスですがObject
、1 つの特別なプロパティがあります。
オブジェクトのプロパティまたはメソッドにアクセスしようとして、JS がインスタンス レベルで定義されたこのプロパティを見つけられない場合、JS はプロトタイプ プロパティの名前を解決しようとします。
instance.nonExistantProperty;
//js scans instance variable, doesn't find property:
instance.prototype.nonExistantProperty
//js uses prototype, if not found:
instance.prototype.prototype.nonExistantProperty
//all the way up to Object.prototype, which does not have a prototype, so here an exception is raised (TypeError is thrown)
ここに私の古い投稿の 1 つからコピーしたこのルックアップの短い概略図を示します。一見の価値があるかもしれません。下部にあるリンクされた回答も確認してください。この問題についてさらに詳しく説明しています。
[ F.divide ]<=========================================================\ \
F[divide] ===> JS checks instance for property divide | |
/\ || | |
|| || --> property found @instance, return value-------------------------------| |
|| || | |
|| ===========> Function.prototype.divide could not be found, check prototype | |
|| || | |
|| ||--> property found @Function.prototype, return-----------------------| |
|| || | |
|| ==========> Object.prototype.divide: not found check prototype? | |
|| || | |
|| ||--> property found @Object.prototype, return---------------------|_|
|| || |=|
|| =======>prototype is null, return "undefined.divide"~~~~~~~~~~~~~~~|X|
|| \ /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined
基本的にはそれだけです。
さて、おそらくあなたも、なぜ関数をFoo.prototype.constructor
参照するのかについて少し挫折しているでしょう。
繰り返しますが、これは非常に簡単です。各インスタンスには、処理しているオブジェクトのタイプを決定するために必要なすべての情報が含まれていることが期待されるからです。Foo
function Foo{}
var inst = new Foo();
console.log(inst.constructor);//references the constructor function
によって返されるすべてのインスタンスは、すべてのプロパティと (オプションで) インスタンス レベルの一部のプロパティFoo
も参照するオブジェクトを返すことに注意してください。prototype
では、なぜわざわざそのようなインスタンスを作成するのでしょうか? 繰り返しますが、これは完全に単純です: インスタンスを変更しても、プロトタイプは変更されません:
console.log(Foo.prototype.constructor === inst.constructor);//true
inst.constructor = function(){};//override constructor property
console.log(Foo.prototype.constructor === inst.constructor);//false, prototype did not change