如何使用链式 javascript 原型继承?
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__
是我想避免的事情
[编辑]
我大致了解它是如何工作的。
设置 thing1.b 会设置 Thing 实例的 b 属性。它不会触及原型链中定义的Entity.b。
无法在事物实例上设置 thing1.aa ,因为它会抛出“无法在未定义时设置”错误。 此时它沿着原型链向上查找已定义的 Entity.a 并将 Entity.aa 设置为新值。
[进一步编辑]
正如 @IvoWetzel 所说,设置 thing1.b 不会触及原型链,因为设置属性不会。设置 thing1.aa 需要执行两个步骤。 thing1.a 上的 getter 触及原型链,后跟 .a 的 setter
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
I'm having difficulty with setting prototypical inheritance in javascript. Ideally I want both thing1 and thing2 to have their own clean copy of the "new Entity prototype".
using this.__proto__
is something I want to avoid
[Edit]
I have a rough idea of how this working.
Setting thing1.b sets the b property on the Thing instance. which does not touch the Entity.b defined in the prototype chain.
Where as setting thing1.a.a on the Thing instance cannot been done because it would throw an "cannot set a on undefined" error. That's when it goes up the prototype chain to find Entity.a which is defined and sets Entity.a.a to a new value.
[Further Edit]
As @IvoWetzel says setting thing1.b does not touch the prototype chain because setting properties does not. Where as setting thing1.a.a does two steps. A getter on thing1.a which touches the prototype chain followed by a setter of .a
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以做的一件事是在
Thing
中应用Entity
构造函数的逻辑,例如:A thing you could do is to apply the logic of your
Entity
constructor insideThing
, for example:虽然 CMS 已发布解决方案,但为什么
thing2.b
返回 5 以及为什么thing2.aa
解析为对象?所有的麻烦都在于 JavaScript 沿着原型链向上查找属性。但是,当您设置属性时,它不会沿着链向上移动。
While CMS has posted a solution, why does
thing2.b
return 5 and why doesthing2.a.a
resolve to the object?All the trouble is about JavaScript going up the prototype chain in order to find properties. But when you set properties it does not go up the chain.
这是因为 JavaScript 对象始终被视为引用。
因此,当您通过执行
aaa = 3;
更改this.a
对象时,您正在更改内存中的该对象。Thing
的新实例将引用内存中的同一对象,因为Entity
构造函数不会在每次Thing
调用时调用,并且this .a
对象保持不变。我会将
this.a
放在原型链之外,可能直接放在Thing
构造函数内。这将使每次实例化Thing
时都会在内存中创建新版本的this.a
。That's because JavaScript objects are always treated as references.
Therefore when you change the
this.a
object by doinga.a.a = 3;
you're changing that one object in memory. New instances ofThing
will reference that same object in memory because theEntity
constructor is not called every timeThing
is, and thethis.a
object remains the same.I would put
this.a
outside the prototype chain, probably directly inside theThing
constructor. This would make it so that a new version ofthis.a
is created in memory every timeThing
is instantiated.