JavaScript プロトタイプ オブジェクトとプロトタイプ チェーンの完全な理解

プロトタイプオブジェクトとプロトタイプチェーン


JavaScript の中核の 1 つは、習得しなければならない知識ポイントでもあります。まずは予防接種を受けてください、知識が多く、非常に抽象的でわかりにくいですが、分かりやすく説明して、あとはご理解次第です。

まず、出現するキーワードをいくつか挙げておきます (すべてを理解している場合は、この記事を読む必要はありません)。

  • プロトタイプ オブジェクトプロトタイプ チェーンコンストラクター

  • [[プロトタイプ]]プロトタイプ__proto__これ


1. これの動的バインディング(予備知識)

プロトタイプを学ぶ前に、JavaScript でのプロトタイプの動的バインディングを理解する必要があります。Java や C++ などのプログラミング言語では、これは現在のインスタンス オブジェクトの参照を表し、この参照は現在のオブジェクトにバインドされており、変更されません。しかし、JavaScript では、これの指示は同じものではありません。最初に簡単な例を見てみましょう。

var date = "Monday";		//这实际上就是 var window.date = "Monday";

function func() {
    
    
    /* 你可能会好奇,这只是一个函数,哪来的 this?
    还记得 window 全局对象吗,this 默认绑定的就是它,所以下面这句话实际上输出的是 window.date */
    console.log("Today is " + this.date);
}

func();

//接下来我们写一个对象,往对象中添加 date 属性
var obj = {
    
    
    date: "Sunday",
    func: function () {
    
    
        //此时的 this 绑定的就是 obj 对象
        console.log("Today is " + this.date);
    }
}
obj.func();

コンソールの出力結果 (ちなみに、ここでは 2 つの関数のこの点を出力しました):

36


まずこれについてはこれくらいにしておきますが、現時点で知っておく必要があるのは次の 2 つのことだけです。

  • これは関数自体を指すものではありません
  • this のバインディングは関数が呼び出されたときに発生し、this が指す場所は関数が呼び出される場所に完全に依存します。


2. 関数のプロトタイプ

JavaScript では、すべての関数には関数のプロトタイプ オブジェクトを指すプロトタイプ プロパティがあり、このオブジェクトには関数自体を指すコンストラクター プロパティがあります1 つの文の中にいくつかの新しい概念が連続して登場しました。少なくとも、めまいがするはずです。大丈夫です。それを絵で表現しましょう。

37


ぐるっと回って、機能自体に戻りますが、それは役に立ちますか?それは役に立つに違いない、役に立たないなら人々はこれをするだろうか?


インスタンス オブジェクトが作成されると、そのコンストラクターが呼び出されることは誰もが知っています。JavaScript の関数のプロトタイプはオブジェクトを指しており、このオブジェクトにはコンストラクターもあるので、その関数を使用してインスタンス オブジェクトを作成できるでしょうか。

上記を理解できれば、最初のステップは成功です。2 番目のステップは、問題の作成方法です。実際は非常に簡単です。new を使用します (はい、JavaScript には new が存在します。新しいのが怖い学生は、実行してください)エスケープではありません)、オブジェクト名 = 新しい関数名 () にします。一見すると、関数にはコンストラクターがありませんが、そのプロトタイプ オブジェクトにはコンストラクターがあります。新しい関数名 () を作成すると、関数はプロトタイプ属性を通じてそのプロトタイプ オブジェクトを見つけます。 , プロトタイプ オブジェクトはそのコンストラクターを呼び出します。このコンストラクターは、func.prototype.constructor としてコードで表されます。賢明な方であれば、すでに発見されているはずです。おい、これは関数そのものではないでしょうか? 信じられない場合は、コンソールを試してみてください.log(func === func.prototype.constructor) を実行して、出力が true かどうかを確認します。要約すると、関数をコンストラクターとして使用し、new キーワードを使用してインスタンス オブジェクトを作成できます。

インスタンス オブジェクトはプロパティやメソッドを持たないので、単にインスタンス オブジェクトを作成するだけでは十分ではありませんが、このときコンストラクタが関与することが多いと思いますが、ここでのコンストラクタは関数そのものであるため、関数内で直接使用できますか?これは? 答えは「はい」で、この動的バインディングの問題を JavaScript で使用することです。上で述べたように、これはデフォルトでは window オブジェクトにバインドされますが、new の時点では、プロトタイプ オブジェクトがコンストラクター (つまり関数自体) を呼び出しているため、この時点ではインスタンス オブジェクトにバインドされます。 be createdは自然に設定されます The object is the property of the object. この文をよく理解できない場合は、コードを注意深く読むことを忘れないでください。

プロパティの問題は解決しましたが、最終的にはメソッドが必要になり、関数のプロトタイプオブジェクトにメソッドを持たせたいので、関数に直接設定しても意味がありません。それで今何をすべきですか?実際、これは非常に簡単で、prototype 属性を使用して関数のプロトタイプ オブジェクトを見つけ、オブジェクトのメソッド名 = function (parameter) {} (忘れた場合は、 JavaScript オブジェクトに関する基本的な知識)

//对了,这里说一个规范,当这个函数我们准备充当构造函数的时候,需要大写首字母哦
function Person(obj) {
    
    
    // || 右边的代表默认值,即不赋值的情况下属性的默认值
    this.name = obj.name || "UnName";
    this.age = obj.age || "-1";
}

//直接在函数上面添加方法(错误)
//Person.run = function(){
    
    
//	console.log(this.name + " 在跑步");
//}

//使用 prototype 增加 Person 原型对象的方法(正确)
Person.prototype.run = function () {
    
    
    console.log(this.name + " 在跑步");
}

Person.prototype.eat = function () {
    
    
    console.log(this.name + " 在吃饭");
}

let Mike = new Person({
    
    name: "Mike", age: 21});
Mike.eat();					//输出 Mike 在吃饭
Mike.run();					//输出 Mike 在跑步

OK、それでは上の画像を更新してみましょう。

202201181415616.jpg



3. オブジェクトの [[Prototype]] ( __proto__ )

最後に、オブジェクトに関して言えば、JavaScript のすべてのオブジェクトに[[Prototype]]という隠し属性があります(両側の括弧を削除しないように注意してください。これは Chrome などのほとんどのブラウザでも__proto__という名前です)、 [[Prototype ]] は、現在のオブジェクトのプロトタイプはい、関数のプロトタイプ オブジェクトです。JavaScript が現在のオブジェクトでプロパティまたはメソッドを見つけられない場合、[[Prototype]] を通じてそのプロトタイプ オブジェクトに委任します (委任: 簡単に理解すると、プロトタイプ オブジェクトで必要なプロパティとメソッドを見つけることができます)。

次に、グラフの更新を続けます。

202201241338110.jpg


上の図から、関数のプロトタイプとオブジェクトの [[Prototype]] が同じプロトタイプ オブジェクトを指していることがわかります。

//还是用上边 Person 代码哈,浏览器中 __proto__ 就是 [[Prototype]]
console.log(Mike.__proto__ === Person.prototype);		//输出 true,自己动手,丰衣足食


4. プロトタイプチェーン

プロトタイプ チェーンとは何ですか? オブジェクト (オブジェクト A とします) のプロパティにアクセスしたい場合、JavaScript はまずターゲット プロパティがオブジェクト A 自体に存在するかどうかをチェックします。存在しない場合は、その [[ を通じてチェックします。プロトタイプ]] オブジェクト B (オブジェクト B と仮定) のプロトタイプ オブジェクトには検索する属性がありません。それでも存在しない場合は、ターゲット属性が存在するまでオブジェクト B (オブジェクト C と仮定) のプロトタイプ オブジェクトの検索を続けます。属性が見つかった、または null が見つかった (つまり、 Object は見つかったが、プロパティが見つからなかった)。ここで、オブジェクトA —> オブジェクト B —> オブジェクト C —> … —> オブジェクトはプロトタイプ チェーンの基本モデルです。

関係図の最終更新:

202201241347628.jpg



次に、プロトタイプ、[[Prototype]]、プロトタイプ オブジェクト、およびプロトタイプ チェーンに関するすべての理論的知識を紹介した後、要約を作成しましょう。

  • 各関数にはプロトタイプ属性があり、そのプロトタイプ オブジェクトを指します。
  • 関数のプロトタイプ オブジェクトには、関数自体であるコンストラクターを指すコンストラクター属性があります。
  • 各オブジェクトには [[Prototype]] 属性があり、そのプロトタイプ オブジェクトを指します。
  • プロトタイプ オブジェクトは、[[Prototype]] を通じてそのプロトタイプ オブジェクト、つまりプロトタイプのプロトタイプを指すこともできます。
  • プロトタイプ チェーンは各プロトタイプ オブジェクトを通じて形成されます

おすすめ

転載: blog.csdn.net/qq_52174675/article/details/122662884