我不明白为什么会发生以下情况:
function Class() {}
Class.prototype.foo = {a: 1};
Class.prototype.bar = 1;
x = new Class();
y = new Class();
y.foo.a = 2;
y.bar = 2;
x.foo.a; //2
x.bar; //1
当我将y.foo.a
设置为2时,它似乎执行与y.constructor.prototype.foo.a = 2
相同的操作。鉴于y.bar = 2
不影响y.constructor.prototype.bar
?
答案 0 :(得分:3)
您正在将原型属性与 local 的属性混合到对象实例。使用y.bar = 2
,您将实例属性(bar
)分配给实例 y
。在解释属性(bar
)时,首先要在实例本身中查找。如果在那里找不到,则在实例原型中继续查找。现在您已将bar
分配给y
,因此y.bar = 2
,但实例x
不知道它,因此对于x
,查找将继续使用其原型(即prototype.bar
,仍有价值1)。
对于y.foo.a
,foo
中没有实例属性y
,因此它会在原型中查找。在那里找到它,并为属性a
分配新值。因为您正在更改Class.prototype
属性foo
的值,所以它也会在x
中表示。
如果你想在原型中更改bar(因此来自实例y
),你必须使用y
的{{1}}原型constructor
(Class
1}}):
y.constructor.prototype.bar = 2;
May mr Douglas Crockford可以为你澄清一些事情(跳转到原型继承视频中的第23分钟左右)?
答案 1 :(得分:0)
如果未在主对象中定义,则读取属性会在原型对象中进行搜索。
设置属性确实将其设置为主对象,而不是原型对象。
因此,定义除函数之外的其他东西或在原型对象中永远不会改变的值是一个坏主意。
要真正了解会发生什么,我建议您尝试
__proto__
属性。我知道,并非所有浏览器都支持它,但它确实有助于您了解JavaScript中的原型设计是如何工作的。
答案 2 :(得分:0)
您正在阅读y.foo
,但已分配给y.bar
。这些是具有不同语义的不同操作。设置y.foo.bar
必须先阅读y.foo
:它会在foo
中查找y
的值,找不到它,然后查看y
的原型,发现一个对象,然后才修改该对象。分配y.bar只是查找y然后修改它。 x.bar
和y.bar
表示不同的对象,而x.foo
和y.foo
表示同一个对象。