有人能以合理的方式向我解释:
function One() {}
One.prototype.obj = { key: 'value' };
One.prototype.str = 'string';
var inst1 = new One(),
inst2 = new One();
// now let’s change some things in our second instance
inst2.obj.key = 'buh!';
inst2.str = 'buh!';
// ok, so what happens to our other instance?
console.log( inst1.str ); // Yields 'string' (unaffected, expected)
console.log( inst1.obj.key ); // Yields 'buh!' (!!)
console.log( One.prototype.obj.key ); // is also 'buh!'
似乎如果原型包含一个对象,那么使用new
关键字创建的实例具有该对象,但如果更改它,则还会更改原型对象,从而影响所有实例,如兄弟-inheritance图案...
这是假设工作的方式吗?
答案 0 :(得分:2)
简而言之,是的。 Javascript不会为您隐式复制对象,因此当您在obj
创建对象文字时,One
类的所有实例都只是通过引用引用它。相反,您需要在构造函数中动态创建obj
对象:
function One(){
this.obj = {key:'value'};
}
答案 1 :(得分:2)
实际上,Javascript不会复制原型中的任何内容。您在原型上定义的所有内容只存在一次(在原型本身上)并被重用,因为相同的原型实例将传递给所有对象。
当您访问对象上的属性时,该对象会检查它是否已在其自身上定义。如果是,则返回与该属性关联的值。如果不是,它会将调用委托给它的原型,后者将从现在起对发生的事情负责。这就是为什么Javascript中的“继承”(代码重用)更好地称为委托。
写访问的情况有点不同。如果在对象上设置属性,它将在本地“隐藏”该值。这就是为什么str属性不受影响的原因,它实际上是在inst2对象上定义的。但是,如果您delete inst2.str
并执行另一个console.log( inst2.str )
,您会发现它会返回旧值。
PS: 如果您想要一种防止这种情况发生的方法,请查看本教程:http://kevlindev.com/tutorials/javascript/inheritance/index.htm
我建议阅读整篇文章,但是如果您只是想让肉看到“创建子类”部分中的KevLinDev.extend函数。