一つの問題からJSプロトタイプのチェーンを解読します.


以前はjsプロトタイプとプロトタイプチェーンの理解がずっと回りくどいと思っていましたが、「JavaScript高級プログラム設計」と各種の文章を見て、ようやくプロトタイプとプロトタイプチェーンについて初歩的な理解ができました.しかし、まだ深く理解していません.今回は以前出会った問題を通して、自分の考えで分析してみます.プロトタイプとプロトタイプチェーンに対する自分の理解を深める.
一、テーマ
次のプログラムの実行結果は何ですか?
function Animal() {
    this.name = 'Animal';
}

Animal.prototype.changeName = function (name) {
    this.name = name;
}

function Cat() {
    this.name = 'Cat';
}

var animal = new Animal();

Cat.prototype = animal;
Cat.prototype.constructor = Cat;

var cat = new Cat();

animal.changeName('Tiger');

console.log(cat.name)
A.アニマルB.Cat C.Tiger D.全部ではありません.
答えはB Catです
二、解読
1.原型の対象
いつでも、新しい関数を作成すると、特定のルールに従って関数を作成します.prototype属性で、この属性は関数のプロトタイプオブジェクトを指す.デフォルトでは、すべての原型オブジェクトが自動的に一つずつ獲得されます.constructor(コンストラクタ)属性は、この属性が指向性です.prototype属性所在関数のポインタ.
次に図を用いて説明する.
function Animal() {
    this.name = 'Animal';
}
Animal.prototype.changeName = function (name) {
    this.name = name;
}
まずAnimal関数を作成しました.Animalにはprototype属性が含まれています.Animal Prottypeを指しています.Animal.prototype.constructorはAnimalを指しています.このとき、name属性は関数で定義されているので、Animal Prottypeではなく、changeName 関数はAnimal.prototype.changeNameで定義されているので、このように複数のオブジェクトを実装する際に原型が保存されている方法を共有することができる.同じように、Cat関数が作成された場合も同じです.
function Cat() {
    this.name = 'Cat';
}
2.作成例
コンストラクタを呼び出して新しい例を作成すると、この例の内部にはコンストラクタのプロトタイプオブジェクトを指すポインタ(内部属性)が含まれます.ECMA-622の第5版の中でこの指針を管理して叫びます.[[Prototype]].スクリプトには標準的なアクセスはありませんが[[Prototype]]ですが、Firefox、Safari、Chromeは各オブジェクトに一つの属性をサポートします.__proto__.重要な点を明確にして、この接続はインスタンスとコンストラクタのプロトタイプオブジェクトの間に存在し、インスタンスとコンストラクタの間に存在しない.
//  Cat       animal  ,  animal    ,       
Cat.prototype = animal;
この部分はこれに相当し、Catのプロトタイプオブジェクトのポインタをanimal例に向けて指すので、元のCatプロトタイプオブジェクトのconstructor属性は失われ、animal例の属性に置き換えられ、name属性および__proto__内部属性を含む__proto__属性もAnimal.prototypeを指す.したがって、Catは、プロトタイプチェーン検索によって、アニマルに呼び出される属性と方法をも用いることができる.
//         constructor,  Cat    
Cat.prototype.constructor = Cat;
この部分は相当しており、元のオブジェクトにconstructor属性を作成し、同時にCat構造関数を指す.
var cat = new Cat();   //      Cat  ,    Animal  
3.呼び出し方法
animal.changeName('Tiger');
var animal = new Animal();がAnimalオブジェクトを実装すると、animalは内部属性を含み、Animal.prototypeを指す.言い換えれば、animalは、構造関数Animalと直接関係がない.しかし、例ではchangeNameを含まないが、animal.changeName(name)を呼び出すことができ、これはオブジェクト属性を検索するプロセスによって実現されることができる.
まず、検索例におけるanimalchangeNameの方法があるかどうか、ない場合は引き続き探し、Animal.prototypeに行ってchangeNameの方法があるかどうかを探し、ある場合は呼び出し、ない場合は引き続き探し、Object.prototypeに探し、最後に見つからなかったらnullに戻る.
ここでの例animalにはchangeName方法がないので、Animal.prototypechangeName方法を探す必要があり、animalの例のnameTiger属性の変更に成功したCat.prototype属性を呼び出す必要があることは明らかである.
このとき、animalはインスタンスCat.prototypeを指すので、nameTigerの属性もcat.nameとなる.
console.log(cat.name)  // Cat
最後に、catを取得すると、検索方法と同様に、name属性が含まれているかどうかを最初に例で調べ、ここでは明らかに存在しているので、直接に検索を終了し、cat.name = 'Cat'.
三、まとめ
この問題を通じて、プロトタイプとプロトタイプチェーンに対する理解が深まりました.実はこの問題は継承に関する知識点にも拡張できます.JavaScriptでの継承は主にプロトタイプチェーンによって実現されます.あとはもっとはっきりしたら書き続けます.
この文章は本人自身がプロトタイプとプロトタイプチェーンについての小さな理解です.中には偏差や間違いがあるかもしれません.よろしくお願いします.