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

プライマー

興味深いことに、JavaScript のオブジェクト指向設計の考え方は、他のオブジェクト指向言語 (Java、Python など) の考え方とは異なります。

JavaScript はオブジェクト指向言語ですが、JavaScript はクラスを使用したり、クラスを作成したり、クラスを通じてオブジェクトを作成したりしません。幸いなことに、Es6の登場によりこの状況は変わりました(公式も元々のJavaScriptのデザインが少し味気ない、と感じていたようです)。Es6 より前は、JavaScript のオブジェクト指向の一連の問題 (オブジェクトの一意性、抽象化、継承、ポリモーフィズム) を解決するには、プロトタイプ チェーンを使用する必要がありました。プロトタイプチェーンの最大の役割は、オブジェクトの継承の問題を解決することです。

JavaScript では、すべてがオブジェクトです。コンストラクター (Function) はオブジェクトであり、コンストラクターのプロトタイプ オブジェクト (Function.prototype) もオブジェクトです。オブジェクトは __proto__ という属性を持ち、 __proto__ はオブジェクトを構築するコンストラクターのプロトタイプ オブジェクトを指し、コンストラクターには、独自のプロトタイプ オブジェクトを指す属性prototypeが含まれます。プロトタイプ オブジェクトには属性コンストラクターがあり、プロトタイプ オブジェクトに関連付けられたコンストラクター (constructor.prototype.constructor==constructor) を指します。__proto__ はすべてのオブジェクトが持つ属性、prototype は関数またはコンストラクターのみが持つ属性、constructor はプロトタイプ オブジェクトのみが持つ属性であることに注意してください。

Es6 が以前どのように継承を実装したかを説明するために、コンストラクターとは何なのか、プロトタイプ オブジェクトとは何なのかを 1 つずつ説明しましょう。

コンストラクタ

他のオブジェクト指向言語とは異なり、JavaScript では新しいクラスを使用してオブジェクトを生成するのではなく、新しい関数を使用してオブジェクトを生成します。新しい関数をコンストラクターと呼び、生成されたオブジェクトをコンストラクター インスタンス オブジェクトと呼びます。

関数がコンストラクターとして使用される場合、その関数内の this ポインターは window や unknown を指すのではなく、作成されたインスタンス オブジェクトを指すことに注意してください。

次の例のように、Person は atuo のコンストラクターであり、atuo は Person のインスタンス オブジェクトです。

function Person(name){
    
    
    this.name = name
}
var atuo = new Person("atuo") 

ここに画像の説明を挿入

プロトタイプオブジェクト

コンストラクターには、コンストラクターのプロトタイプ オブジェクトを指すプロトタイプ属性があります。つまり、いわゆるプロトタイプ オブジェクトがプロトタイプ オブジェクトであり、コンストラクターによって生成されたインスタンス オブジェクトは、コンストラクターを介してコンストラクターを指します。 __proto__ プロトタイプ オブジェクト。

すべてのインスタンス オブジェクトはコンストラクターの同じプロトタイプ オブジェクトを共有するため、一般的には、プロトタイプ オブジェクトに固定で不変の属性値を配置し、すべてのインスタンス オブジェクトがそれを継承するようにします。この属性は参照属性とも呼ばれます。プロトタイプ オブジェクトは、インスタンス オブジェクトの共有変数およびメソッドとして理解され、独自のニーズに応じて動的に変更できるさまざまなインスタンス オブジェクトの属性値がコンストラクターに配置され、この属性はローカル属性。インスタンスが特定の属性を検索するときに、そのローカル属性が見つからない場合は、参照属性を検索します。つまり、インスタンスを構築するコンストラクターのプロトタイプ オブジェクトを検索します。この点については、 JavaScript の継承メカニズムの設計思想を利用できます

function Person(name){
    
    
    this.name = name
}
Person.prototype.age = 21
var atuo = new Person("atuo")
console.log(atuo.age)

ここに画像の説明を挿入

上記の atuo インスタンスにローカル属性名と参照属性 age がある場合、age を検索するときに、そのコンストラクターの属性で見つからない場合 (つまり、ローカル属性で見つからない場合)、追跡されます。コンストラクターのプロトタイプ オブジェクトに戻ります。それは Person.prototype で見つかります。

コンストラクター、プロトタイプ オブジェクト、インスタンス オブジェクトの関係を図に示します。
ここに画像の説明を挿入

プロトタイプチェーン

上記のコンストラクタ、プロトタイプオブジェクト、インスタンスオブジェクトの関係を合成します。では、あるコンストラクターのプロトタイプ オブジェクトを別のコンストラクターのインスタンスと等しくするとどうなるでしょうか? 当然、このときのプロトタイプオブジェクトには、別のコンストラクタのプロトタイプオブジェクトを指すポインタ __proto__ が含まれており、これに対応して、プロトタイプオブジェクト間のチェーンもこのような漸進的な進行によって形成されます。プロトタイプ オブジェクトのチェーンは、__proto__ のチェーンに沿って進行します。これがいわゆるプロトタイプチェーンの基本概念です。

プロトタイプ チェーンを説明するために、次のコードを例に挙げます。

function Student(name){
    
    
    this.name = name
}
Student.prototype.hello = function(){
    
    
    alert('Hello, ' + this.name + '!');
};
var xiaoming = new Student("xiaoming")
var xiaohong = new Student("xiaohong")

以下の図に示すように、黄色でマークされた線がプロトタイプ チェーンです。

ここに画像の説明を挿入

継承する

上記では、プロトタイプ チェーンの関連概念を簡単に説明しましたが、次に、プロトタイプ チェーンを使用して 2 つの「クラス」の継承を実装します。親コンストラクターと子コンストラクターがある場合、それらは互いに何の関係もありません。図に示すように、プロトタイプ チェーンは重なっていません。

ここに画像の説明を挿入

2 つのプロトタイプ チェーンが重なるように、子が親から継承するようにコードを記述します。

function extend(Child, Parent) {
    
    
	var F = function(){
    
    };
	F.prototype = Parent.prototype;
	Child.prototype = new F();
	Child.prototype.constructor = Child;
	Child.uber = Parent.prototype;
}

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/atuo200/article/details/108245426