Chained JavaScriptプロトタイプ継承を使用するにはどうすればよいですか?
-
27-09-2019 - |
質問
function Entity() {
this.a = {a: 4};
this.b = 5;
}
function Thing() {}
Thing.prototype = new Entity;
var thing1 = new Thing;
thing1.a.a = 3;
thing1.b = 4;
var thing2 = new Thing;
console.log(thing2.a.a); // prints 3 instead of 4. I would like 4.
console.log(thing2.b) // prints 5 as wanted
JavaScriptでプロトタイプの継承を設定するのに苦労しています。理想的には、Thing1とThing2の両方が「新しいエンティティプロトタイプ」の独自のクリーンなコピーを持っていることを望んでいます。
使用 this.__proto__
避けたいものです
編集
私はこれがどのように機能するかについての大まかな考えを持っています。
SETTHSTHING1.Bは、ThingインスタンスにBプロパティを設定します。プロトタイプチェーンで定義されているentity.bに触れません。
Thingインスタンスでthing1.aaを設定すると、「未定義のエラーに設定できない」エラーをスローするため、実行できません。 そうです プロトタイプチェーンを上ってEntity.aを見つけて定義され、Entity.AAを新しい値に設定します。
さらに編集
@ivowetzelが言っているように、Sthing1.bはプロトタイプチェーンに触れないため、プロパティの設定はそうではありません。 shing1.aaの設定として2つのステップを実行します。 a ゲッター onthing1.aは、プロトタイプチェーンに続いて.aのセッターが続きます。
解決
あなたができることは、することです 申し込み あなたの論理 Entity
内部のコンストラクター Thing
, 、 例えば:
function Entity() {
this.a = {a: 4};
this.b = 5;
}
Entity.prototype.c = 6;
function Thing() {
Entity.apply(this, arguments); // ejecutes the assignments made in Entity
}
Thing.prototype = new Entity;
var a = new Thing;
a.a.a = 3;
var b = new Thing;
console.log(a.a.a); // 3
console.log(b.a.a); // 4
console.log(a.b); // 5
console.log(b.b); // 5
console.log(a.c); // 6
console.log(b.c); // 6
他のヒント
CMSがソリューションを投稿している間、なぜそうです thing2.b
5を返し、なぜそうするのですか thing2.a.a
オブジェクトに解決しますか?
var thing1 = new Thing;
// thing1 has no a, but the prototype has so a.a is essentially the a of Entity
thing1.a.a = 3;
// Sets b on thing1, setting does not go up the prototype chain(!)
thing1.b = 4;
// that's what thing1 looks like
Thing {proto: Entity {
a: { <--- gets resolved
a: 3 <-- gets set
},
b: 5
},
b: 4 <-- gets set directly
}
var thing2 = new Thing;
// thing2.a does not exist, so we look up the prototype and find a on Entity
console.log(thing2.a.a);
// thing2.b also does not exists, so once again we look up the prototype to find b on Entity
console.log(thing2.b);
// that's what thing2 looks like
Thing {proto: Entity {
a: {
a: 3 <- gets resolved
},
b: 5 <- gets resolved
}
}
すべての問題は、JavaScriptがプロパティを見つけるためにプロトタイプチェーンを上げることについてです。しかし、プロパティを設定するとき ではない チェーンを上ってください。
これは、JavaScriptオブジェクトが常に参照として扱われるためです。
したがって、変更するとき this.a
してオブジェクト a.a.a = 3;
その1つのオブジェクトをメモリに変更しています。の新しいインスタンス Thing
そのために同じオブジェクトをメモリ内に参照します Entity
コンストラクターは毎回呼び出されません Thing
IS、そして this.a
オブジェクトは同じままです。
私は置きます this.a
プロトタイプチェーンの外側、おそらく直接の内側 Thing
コンストラクタ。これにより、新しいバージョンが this.a
毎回メモリで作成されます Thing
インスタンス化されています。