在我的JavaScript项目中,我定义了一个对象,然后使用Object.create()创建多个实例。该对象具有多个(字符串和整数)属性,每个属性对于每个实例都是唯一的。但是,如果我使用数组属性,则所有实例共享相同的数组。
此代码很容易证明:
TestThing = {
code: "?",
intlist: [],
addint(i) {
alert("Adding " + i + " to " + this.code + ", list had " + this.intlist.length + " ints");
this.intlist.push(i);
}
}
var thing1 = Object.create(TestThing);
thing1.code = "Thing 1";
var thing2 = Object.create(TestThing);
thing2.code = "Thing 2";
thing1.addint(11);
thing2.addint(42);
alert(thing2.intlist); // will output 11,42
那是什么原因造成的?我该如何解决这个问题?
答案 0 :(得分:1)
使用reference-type属性,每个子节点都会获得对同一对象的引用。所有实例都可以看到任何孩子对该对象所做的任何更改。
您需要实现构造函数来设置属性,或者让第一次使用属性的代码设置它。 (但是,如果你想使用构造函数和 Object.create
,你必须自己调用它; Object.create
不会为你调用它。 )
你可以这样做......
TestThing = {
code: "?",
intlist: null,
addint : (i) => {
if (!this.intlist) this.intlist = [];
alert("Adding " + i + " to " + this.code + ", list had " + this.intlist.length + " ints");
this.intlist.push(i);
}
}
或者,更不容易出错(虽然放弃Object.create
)......
class TestThing {
constructor(code) {
this.code = code;
this.intlist = [];
}
addint(i) {
alert("Adding " + i + " to " + this.code + ", list had " + this.intlist.length + " ints");
this.intlist.push(i);
}
}
var thing1 = new TestThing("Thing 1");
var thing2 = new TestThing("Thing 2");
thing1.addint(11);
thing2.addint(42);
alert(thing2.intlist); // will output 42
不幸的是,如果您正在为网络浏览器编码,那么IE(甚至IE 11)似乎并不支持class
。因此,您必须坚持使用旧的定义类的方式。
TestThing = function(code) {
this.code = code;
this.intlist = [];
};
TestThing.prototype = {
addint: function(i) {
alert("Adding " + i + " to " + this.code + ", list had " + this.intlist.length + " ints");
this.intlist.push(i);
}
};
答案 1 :(得分:-2)
要解决此问题,请使用concat
代替推送,如下所示:
this.intlist = this.intlist.concat(i);
为什么会这样?因为push
改变了数组,concat
没有,并且javascript中的数组也是一个对象,因此,对该数组的内存引用是相同的。