ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptプロトタイプとプロトタイプチェーンの詳細説明

JavaScriptプロトタイプとプロトタイプチェーンの詳細説明

小云云
小云云オリジナル
2018-03-20 09:46:161439ブラウズ

作成するすべての関数にはプロトタイプ属性があり、この属性はプロトタイプ オブジェクトを指すポインターであり、このプロトタイプ オブジェクト内のプロパティとメソッドはすべてのインスタンスで共有できます。この記事では主に、JavaScript プロトタイプとプロトタイプ チェーンの関連知識ポイントと使用方法の共有について詳しく説明します。興味のある方は参考にしていただければ幸いです。

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true

1. プロトタイプ オブジェクトを理解する

新しい関数が作成されるたびに、特定のルール セットに従ってその関数のプロトタイプ プロパティが作成されます。このプロパティは、関数のプロトタイプ オブジェクトを指します。

デフォルトでは、すべてのプロトタイプ オブジェクトは、プロトタイプ属性が配置されている関数へのポインターを含むコンストラクター属性を自動的に取得します。

新しいインスタンスを作成するためにコンストラクターが呼び出されるとき、インスタンスにはコンストラクターのプロトタイプ オブジェクトを指すポインター (内部プロパティ) が含まれます。 ECMA-262 バージョン 5 では、このポインターを [[プロトタイプ]] と呼びます。

スクリプトで [[Prototype]] にアクセスする標準的な方法はありませんが、Firefox、Safari、Chrome は他の実装のすべてのオブジェクトで __proto__ 属性をサポートしていますが、この属性はスクリプトにはまったく表示されません。

ただし、明確にしておくべき本当に重要な点は、この接続はインスタンスとコンストラクターの間ではなく、インスタンスとコンストラクターのプロトタイプ オブジェクトの間に存在するということです。

Person コンストラクターと Person.prototype を使用してインスタンスを作成する前述のコードを例として、図 6-1 に各オブジェクト間の関係を示します。

ここで、 person.prototype はプロトタイプ オブジェクトを指し、 Person.prototype.constructor は person を指します。

person1 と person2 には両方とも、person.prototype を指すだけの内部プロパティが含まれています。つまり、コンストラクターと直接の関係はありません。

person1.sayName() を呼び出すことができます。これは、オブジェクトのプロパティを見つけるプロセスを通じて実現されます。 (最初にインスタンスを検索し、見つからない場合はプロトタイプの検索を続けます。)


用isPrototypeOf()方法判断实例与原型对象之间的关系
alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true

用Object.getPrototypeOf() 方法返回实例的原型对象
alert(Object.getPrototypeOf(person1) == Person.prototype); //true

使用 hasOwnProperty() 方法可以检测一个属性是存在于实例中,还是存在于原型中。
alert(person1.hasOwnProperty("name")); //false  来着原型
person1.name = "Greg";
alert(person1.name); //"Greg"——来自实例
alert(person1.hasOwnProperty("name")); //true

2. より単純なプロトタイプ構文

前の例では、以下を行う必要があります。プロパティとメソッドを追加するたびに、再度入力します。不必要な入力を減らし、プロトタイプの機能をより視覚的にカプセル化するために、すべてのプロパティとメソッドを含むオブジェクト リテラルでプロトタイプ オブジェクト全体をオーバーライドすることが一般的です。


function Person(){
}
Person.prototype = {
  name : "Nicholas",
  age : 29,
  job: "Software Engineer",
  sayName : function () {
    alert(this.name);
  }
};

上記のコードでは、オブジェクト リテラルとして作成された新しいオブジェクトに person.prototype を設定しています。最終結果は同じですが、1 つの例外があります。コンストラクター プロパティは Person を指さなくなりました。

以前紹介したように、関数が作成されるたびにそのプロトタイプオブジェクトも同時に作成され、このオブジェクトはコンストラクタープロパティも自動的に取得します。


var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(friend.constructor == Object); //true

ここで、instanceof 演算子を使用して Object と Person をテストすると、依然として true が返されますが、コンストラクターのプロパティは Object と等価ですが、Person と等しくありません。

コンストラクターの値が本当に重要な場合は、以下のように具体的に適切な値に戻すことができます。


function Person(){
}
Person.prototype = {
  constructor : Person,
  name : "Nicholas",
  age : 29,
  job: "Software Engineer",
  sayName : function () {
    alert(this.name);
  }
};

3. ネイティブ オブジェクトのプロトタイプ

すべてのネイティブ参照型 ( Object 、 Array 、 String など) には、コンストラクターのプロトタイプでメソッドが定義されています。

たとえば、sort() メソッドは Array.prototype にあり、substring() メソッドは String.prototype にあります。変更することは可能ですが、ネイティブ オブジェクトのプロトタイプを変更することはお勧めできません。

4. プロトタイプ オブジェクトの問題

プロトタイプ パターンの最大の問題は、その共有の性質によって引き起こされます。 いずれかを変更すると、もう一方にも影響します。


function Person(){
}
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
friends : ["Shelby", "Court"],
sayName : function () {
alert(this.name);
}
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
alert(person1.friends === person2.friends); //true

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

基本的な考え方は、プロトタイプを使用して、ある参照型に別の参照型のプロパティとメソッドを継承させることです。次に、層ごとに、インスタンスとプロトタイプのチェーンが形成されます。これが、いわゆるプロトタイプ チェーンの基本概念です。


function SuperType(){
  this.property = true;
}
SuperType.prototype.getSuperValue = function(){
  return this.property;
};
function SubType(){
  this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
  return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true

画像の説明:

propertyはSubType.prototypeにあります。これは、property がインスタンス プロパティであり、getSuperValue() がプロトタイプ メソッドであるためです。 SubType.prototype は SuperType のインスタンスになっているため、当然、プロパティはそのインスタンス内にあります。

関連:

JSプロトタイプとプロトタイプチェーンの詳細説明


以上がJavaScriptプロトタイプとプロトタイプチェーンの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。