我正在尝试创建一个主对象,我可以创建多个实例,每个实例都继承子项(具有唯一/隔离属性)。但是,当我这样做时,对象的属性(在被更改之后)正在改变所有创建的对象。我可能没有正确解释这个,但这个例子应该很清楚。
Main = function(){};
// Extending the main class with new object. Doing it this way so I can have these in
// separate files.
Main.prototype.foo = {
bar: 1
}
// First instance of Main().
var A = new Main();
// Second instance of Main().
var B = new Main();
// Set the bar property to different values for each Main() object.
A.foo.bar = 2;
B.foo.bar = 3;
// Both A.foo.bar and B.foo.bar return 3.
alert(A.foo.bar);
alert(B.foo.bar);
我想要发生的事情是,A.foo.bar返回2而B.foo.bar返回3,这样我就有了彼此独立的孤立对象。
有什么想法吗?我只是错过了一些明显的东西吗?非常感谢!
答案 0 :(得分:5)
“foo”属性位于原型对象上,并且只有其中一个属性。当您通过任何实例设置它时,您正在影响同一个共享属性。
您可以在构造函数中添加实例属性:
function Main() {
this.instanceProperty = 1;
}
然后那将是每个实例。
原型不是“主模板”或类似的东西;这是一个真实的对象。它不会复制到实例上。相反,运行时知道它就在那里,并且当对实例上实际不存在的实例上的属性进行引用时,它就知道要走原型链并在那里寻找属性。
答案 1 :(得分:3)
其他答案或多或少是正确的,但他们缺少的是
之间存在差异Main.prototype.foo = {
bar: 1
};
和
Main.prototype.bar = 1;
在这两种情况下,实例化新的Main
都会在其原型链中创建一个新实例,其属性为foo
或bar
。在这两种情况下,都可以重新定义实例级属性,而不会影响其他实例:
function Main() {};
Main.prototype.foo = {
bar: 1
};
Main.prototype.bar = 1;
a = new Main();
b = new Main();
a.foo = { bar: 2 };
console.log(a.foo.bar, b.foo.bar); // 2 1
a.bar = 2;
console.log(a.bar, b.bar); // 2 1
但是当您实例化新的Main
时,实例变量foo
是对单个对象{bar:1}
的引用,它在所有实例之间共享。因此,当您设置a.foo.bar
时,您正在更改公共对象,而不是实例变量;实例变量是引用a.foo
。
您不必在构造函数中初始化实例属性。标准方法是直接在原型上设置bar
,即Main.prototype.bar = 1
,这将为您提供初始化为1
的独立实例变量。但是,如果您需要基于每个实例的更复杂的数据结构(对象,数组或另一个类的实例),那么您不能将其创建为原型上的属性,因为您将成为给每个实例一个对公共对象的引用 - 所以在构造函数中是要走的路:
function Main() {
// instance-level object
this.foo = {
bar: 1
};
}
答案 2 :(得分:1)
由于你在原型上编辑某些东西,它会影响每个对象。
但是,你可以这样做:
A.x = 2;
B.x = 3;
然后你会有不同的结果。
或者,你可以这样:
Main = function(val){
this.x = val;
}
A = new Main(2);
B = new Main(3);