原型と原型チェーンjsを深く理解する

4634 ワード

コンストラクタの作成
function Person() {

}
var person = new Person();
person.name = 'Kevin';
console.log(person.name) // Kevin
Personは構造関数であり、newを用いて例示的なオブジェクトpersonを作成した.
prototype【関数の属性】
各関数にはプロトタイプの属性があり、プロトタイプの属性はオブジェクトを指しています.このオブジェクトは構造関数を呼び出して作成したインスタンスのプロトタイプです.
function Person() {

}
//        ,      :
// prototype         
Person.prototype.name = 'Kevin';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin
Person.prototypeはperson 1とperson 2の原型です.
原型は何ですか?JavaScriptオブジェクトごとに(nullを除く)作成時に別のオブジェクトに関連します.このオブジェクトは私たちが言っているプロトタイプです.どのオブジェクトもプロトタイプから属性を継承します.
元のオブジェクトはインスタンスの中にある属性の一部を保存するために使用されます.
すべてのオブジェクトはそのプロトタイプのオブジェクトによって継承されます.逆に、すべてのオブジェクトはプロトタイプのオブジェクトとして存在することができます.
プロト
実例と実例の原型、つまりpersonとPerson.prototypeの関係を表します.
これは各JavaScriptオブジェクト(nullを除く)が持つ属性の一つです.proto_,この属性はそのオブジェクトの原型を指します.
function Person() {

}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true
例のオブジェクトと構造関数がプロトタイプに向けられるなら、プロトタイプは構造関数またはインスタンスに向けられていますか?
トラック
指差の例はないですが、一つのコンストラクタは複数のインスタンスを生成することができますが、プロトタイプはコンストラクタを指しています.これは第三の属性を述べます.
この点を検証するために、試してみてもいいです.
function Person() {

}
console.log(Person === Person.prototype.constructor); 
以上より、私達はすでに結論を出しました.
function Person() {

}

var person = new Person();

console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
//       ES5   ,         
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
構造関数、インスタンスプロトタイプ、およびインスタンス間の関係を理解しました.次に実例とプロトタイプの関係を説明します.
実例と原型
インスタンスのプロパティを読み込むと、オブジェクトに関連するプロトタイプの属性が見つからない場合は、まだ検出されていない場合は、プロトタイプのプロトタイプを探して最上階まで探します.
例を挙げます
function Person() {

}

Person.prototype.name = 'Kevin';

var person = new Person();

person.name = 'Daisy';
console.log(person.name) // Daisy

delete person.name;
console.log(person.name) // Kevin
この例では、私たちはインスタンスオブジェクトのpersonにname属性を追加しました.私たちがperson.nameを印刷すると、結果は自然にDaisyです.
しかし、私たちはpersonのname属性を削除した時、person.nameを読み、personオブジェクトからname属性が見つからないと、personのプロトタイプ、つまりperson._._._._.u.u.proto_,つまりPerson.prototypeで探してみます.幸いなことに、私たちはname属性を見つけました.結果はKevinです.
でももしまだ見つけられなかったら?原型の原型は何ですか?
原型の原型
前に、私達はもう原型も一つの対象であると言いました.対象である以上、最も原始的な方法でそれを作成することができます.
var obj = new Object();
obj.name = 'Kevin'
console.log(obj.name) // Kevin
実はプロトタイプのオブジェクトはObjectのコンストラクタによって生成され、前述のように、インスタンスのプロトはコンストラクタのprototypeを指す.
原型チェーン
JavaScriptのすべての対象はその原型の対象から継承されます.プロトタイプのオブジェクト自体も対象です.プロトタイプのオブジェクトもあります.こういった段階でさかのぼると、チェーンのような構造になります.これがプロトタイプのチェーンです.
すべてのプロトタイプの終点はObject関数のプロトタイプ属性です.JavaScriptのオブジェクトはデフォルトでObject()で構成されています.Objec.prototypeが指す原型の対象は同じですが、プロトタイプはnullで、nullはプロトタイプがありません.
console.log(Object.prototype.__proto__ === null) // true
しかし、nullは一体何を表していますか?
阮一峰先生の『undefinedとnullの違い』を引用すると、
nullは「対象がない」という意味で、そこに値があるべきではない.
だからObject.prototype.uプロト.の値はnullとObject.prototypeの原型がないという意味です.
属性を検索する時にObject.prototypeを調べたら検索を停止できます.
ちなみに、相互関連のプロトタイプからなるチェーン構造がプロトタイプチェーンです.
追加
最後に、三つのポイントを追加します.みんなが気づかないところ:
トラック
まずconstructor属性です.例を見ます.
function Person() {

}
var person = new Person();
console.log(person.constructor === Person); // true
person.co nstructorを取得すると、実はpersonにはconstructor属性がなく、constructor属性が読み取れない場合、personのプロトタイプであるPerson.prototypeから読み取られます.ちょうどプロトタイプにこの属性があります.
person.constructor === Person.prototype.constructor
プロト
次にプロトであり、ほとんどのブラウザはこの非標準的な方法のプロトタイプへのアクセスをサポートしていますが、Person.prototypeには存在しません.実際にはObject.prototypeから来ています.属性というよりは、getter/setterを使用して、Object.auを使用します.プロト.を返したと理解できます.
本当に継承ですか?
最後に継承についてですが、前に述べたように、「どの対象も原型から継承されます」という属性がありますが、実際に継承は非常に迷いのある言い方です.
継承は複製操作を意味しているが、JavaScriptはデフォルトでは複製対象の属性は認められておらず、逆にJavaScriptは二つのオブジェクトの間に一つの関連を作成するだけで、一つのオブジェクトは依頼によって別のオブジェクトの属性と関数にアクセスすることができるので、継承というよりは依頼の言い方の方がより正確である.
参考文献:
JavaScriptの深く入り込むのは原型から原型の鎖までです。
良い文章の継承について:
JavaScriptの深い継承の多種の方式と長所と短所
一つの文章はJS継承を理解する。