JavaScriptの対象と原型、プロトタイプチェーン
8348 ワード
原文のリンク:https://juejin.im/post/5c4e996ef265da611d670436
オブジェクト
JavaScriptでは、万物はすべてObjectに対象されています.
Objectは属性の集合であり、個々のプロトタイプ
一つのObjectの
プロトとプロトタイプ は関数だけが 原型チェーン
JSは、
公式の注釈:A prototype chain is a finite chain of object s which is used to implemented inherst and shared properties.
構造関数は、
オブジェクトの
jsのオペレータ
クラスをサポートする言語では、
例えば、a 1オブジェクトは、自身
二つの注意点: js検索はいずれも自身から探し始めます.見つけられない時、原型チェーンに沿ってa 1の原型を探します.見つけたら、この方法を呼び出します.見つからない時は引き続き上に探してください.原型がnullである時に、calc()undefinedに戻ります. thisの指向は、メソッドを呼び出したときに決定され、プロトタイプチェーン検索の影響を受けない. 上記のオブジェクト設定
構造関数
上記の例と同様に、a 1の原型は対象aを継承し、構造関数として次のように書き換えます.
回顧総括オブジェクトは、属性 方法は、属性
オブジェクト
JavaScriptでは、万物はすべてObjectに対象されています.
Objectは属性の集合であり、個々のプロトタイプ
[prototype object]
を有しています.このプロトタイプ[prototype object]
は、Objectまたはnull値であっても良いです.一つのObjectの
prototype
は内部の[[prototype]]
属性の参照である.プロトとプロトタイプ
[[prototype]]
は__proto__
であり、__proto__
属性の値はその対応するプロトタイプオブジェクトである.各オブジェクトには__proto__
属性があり、自分が継承したプロトタイプを識別する.typeof function(){}.__proto__ === 'function' // true
typeof {}.__proto__ === 'object' // true
prototype
属性です.関数を作成すると、JSは関数のprototype
属性を自動的に作成します.その値はconstructor
属性のオブジェクトで、この方法のプロトタイプオブジェクトを指します.この関数をコンストラクタとして呼び出すと、JSはコンストラクタの一例を作成してくれます.例はコンストラクタprototype
のすべての属性と方法を継承します.JSは、
__proto__
とprototype
の協力によってプロトタイプチェーンとオブジェクトの継承を実現した.公式の注釈:A prototype chain is a finite chain of object s which is used to implemented inherst and shared properties.
構造関数は、
__proto__
によって共有される属性および方法を格納し、prototype
が既存のオブジェクトを指すように設定してオブジェクトを継承することもできる.オブジェクトの
prototype
は、自己構成関数のprototype
を指す.__proto__
のプロトタイプチェーンは、これによって生成される.jsのオペレータ
prototype
は、obj.__proto__.__proto__...
をプローブすることによって、objがinstanceof
であるかどうかを検証する例である.クラスをサポートする言語では、
obj.__proto__.__proto__... === Constructor.prototype
を通じて、A継承Bを実現することができます.Javascript言語では、類の概念はないが、原型チェーンによって継承されることができます.この実現方法は原型継承です.例えば、a 1オブジェクトは、自身
Constructor
を設定することにより、自身のプロトタイプオブジェクトをaオブジェクトに指向させることにより、プロトタイプ継承が実現される.var a = {
x: 10,
calc: function(z) {
return this.x + this.y + z
}
}
var a1 = {
y: 10,
__proto__: a
}
console.log(`calc ${a1.calc(10)}`) // calc 30
上記の例では、Class A extends B {}
を呼び出したとき、a 1のcall方法を探してみたが、a 1のプロトタイプaに続き、この方法を発見して呼び出すことができなかったと分析した.__proto__
方法には、それぞれ2つのthis上の属性x,yおよび1つの参照zの3つのパラメータがある.オブジェクト属性の呼び出し方式なので、thisはa 1を指し、そのうちa 1はx属性がないので、x属性は原型上のxの値を使い、y属性はa 1の属性を使い、zは10を伝えます.二つの注意点:
a1.calc(10)
または関数設定calc()
に加えて、一般的な作成オブジェクト方式は、コンストラクタである.構造関数
上記の例と同様に、a 1の原型は対象aを継承し、構造関数として次のように書き換えます.
function A(y) {
this.x = 10;
this.y = y;
this.calc = function(z) {
console.log(`x ${this.x}, y ${y}, z ${z}`);
return this.x + this.y + z
};
}
A.prototype.name = 'A name';
var a2 = new A(20)
console.log(`name: ${a2.name}, : ${a2.calc(30)}`);
// x 10, y 20, z 30
// name: A name, : 60
console.log(
a2.constructor === A, // true
a2.__proto__ === A.prototype, // true
a2.name === a2.__proto__.name, // true
a2.name === A.prototype.name, // true
A.__proto__ === A.prototype, // false
`A : ${A.__proto__ === Function.prototype}`, // A : true
`A : ${A.prototype.constructor === A}`, // A : true
);
関数Aを作成すると、JSは関数Aのa1.__proto__ = a
属性を自動的に作成します.その値はfunction A(){}; A.prototype = AA
属性のオブジェクトです.キーワードprototype
を通じて、オブジェクトa 2を作成しました.例a 2は構造関数constructor
のすべての属性と方法を継承しました.回顧総括
function Foo(name) {
this.name = name;
}
var foo1 = new Foo('foo1');
var foo2 = new Foo('foo2');
var obj1 = new Object();
var obj2 = new Object();
console.log(foo1.__proto__ === Foo.prototype); // true
console.log(Foo.prototype.constructor === Foo); // true
console.log(obj1.__proto__ === Object.prototype); // true
console.log(Foo.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.constructor === Object); // true
console.log(Object.__proto__ === Function.prototype); // true
console.log(Function.prototype.constructor === Function); // true
console.log(Function.__proto__ === Function.prototype); // true
new
があり、オブジェクトの構造関数のプロトタイプオブジェクトを指す.prototype
に加えて、属性__proto__
、__proto__
がこの方法のプロトタイプオブジェクトを指す.