Javascript 原型对象可以从实例更改

Javascript 原型对象可以从实例更改,javascript,inheritance,prototype-programming,Javascript,Inheritance,Prototype Programming,有人能给我解释一下吗 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!'; //

有人能给我解释一下吗

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
关键字创建的实例似乎拥有该对象,但是如果您更改它,您也会更改原型对象,从而影响所有实例,就像兄弟继承模式一样


这就是它的工作原理吗?

简言之,是的。Javascript不会为您隐式复制对象,因此当您在
obj
创建对象文本时,
One
类的所有实例都只是通过引用引用它。相反,您需要在构造函数中动态创建
obj
对象:

function One(){
  this.obj = {key:'value'};
}

另请参见:

实际上,Javascript不会复制原型中的任何内容。您在原型上定义的所有内容只存在一次(在原型本身上),并且会被重用,因为相同的原型实例会传递给所有对象

当您访问对象上的属性时,对象会检查是否在其自身上定义了该属性。如果是,它将返回与该属性关联的值。如果不是,它将把调用委托给它的原型,从现在起,原型将负责所发生的事情。这就是为什么Javascript中的“继承”(代码重用)更好地称为委托

写访问的情况有点不同。如果在对象上设置属性,则该属性将在本地“阴影”该值。这就是str属性不受影响的原因,它实际上是在inst2对象上定义的。但是如果您
删除inst2.str
并执行另一个
console.log(inst2.str)
,您会注意到它将返回旧值

附言: 如果您想要一种防止这种情况发生的方法,请参阅本教程:


我建议您阅读全文,但如果您只想查看“创建子类”部分中的KevLinDev.extend函数。

是的,如果您想禁用它,可以冻结一个对象:
object.freeze(One.prototype.obj)。很好,不知道冻结。但是浏览器支持似乎非常狭窄@David所有当前的浏览器都实现了
freeze
<代码>:P
是的,我指的是传统浏览器支持:/I我在回复中添加了一个链接,指向一个在任何地方都可以使用的方法,它在许多库中使用。