在JavaScript中混淆原型行为

时间:2011-05-08 19:22:31

标签: javascript prototype

我不明白为什么会发生以下情况:

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

,为什么会这样呢?

3 个答案:

答案 0 :(得分:3)

您正在将原型属性与 local 的属性混合到对象实例。使用y.bar = 2,您将实例属性(bar)分配给实例 y。在解释属性(bar)时,首先要在实例本身中查找。如果在那里找不到,则在实例原型中继续查找。现在您已将bar分配给y,因此y.bar = 2,但实例x不知道它,因此对于x,查找将继续使用其原型(即prototype.bar,仍有价值1)。

对于y.foo.afoo中没有实例属性y,因此它会在原型中查找。在那里找到它,并为属性a分配新值。因为您正在更改Class.prototype属性foo的值,所以它也会在x中表示。

如果你想在原型中更改bar(因此来自实例y),你必须使用y的{​​{1}}原型constructorClass 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.bary.bar表示不同的对象,而x.fooy.foo表示同一个对象。