我有一个包含数组的对象定义。当我实例化2个对象并访问其成员时,两个对象都写入同一个数组。我期待每个对象都有自己的数组,而不是共享相同的数组。它适用于对象的其他成员。为什么这样做以及这样做的正确方法是什么?以下是示例代码
//define simple object
var OBJ = {
id: 0,
arr: [0,0]
};
//instantiate objects
let obj1 = Object.create(OBJ);
let obj2 = Object.create(OBJ);
//change members value
obj1.id = 1;
obj1.arr[0]=1111;
obj2.id=2;
obj2.arr[1]=2222;
//verify changes
console.log(obj1.id); //id = 1 as expected
console.log(obj1.arr); //<--- expected [1111, 0000] NOT [1111, 2222]
console.log(obj2.id); //id = 2 as expected
console.log(obj2.arr); //<--- expected [0000, 2222] NOT [1111, 2222]
答案 0 :(得分:0)
https://lodash.com/docs/4.17.5#cloneDeep
应该是你想要的,它将以递归的方式复制所有内容
答案 1 :(得分:0)
<强>问题强>
当您使用Object.create()
从OBJ
创建新对象时,OBJ
将成为新对象的原型。所有方法和属性都取自prototype chain,除非该对象具有自己的同名属性,否则会覆盖它们。由于arr
是OBJ
的属性,因此所有对象都会更新,并显示相同的数组。
建议的解决方案
您可以将arr
转换为getter,使用Object.hasOwnProperty()
检查arr
是否是当前对象的属性,如果不是,则克隆原型数组,然后归还。
//define simple object
var OBJ = {
id: 0,
_arr: [0, 0],
get arr() {
if(!this.hasOwnProperty('_arr')) this._arr = [...this._arr];
return this._arr;
}
};
//instantiate objects
let obj1 = Object.create(OBJ);
let obj2 = Object.create(OBJ);
//change members value
obj1.id = 1;
obj1.arr[0] = 1111;
obj2.id = 2;
obj2.arr[1] = 2222;
//verify changes
console.log(obj1.id); //id = 1 as expected
console.log(obj1.arr); //<--- expected [1111, 0000]
console.log(obj2.id); //id = 2 as expected
console.log(obj2.arr); //<--- expected [0000, 2222]
&#13;
答案 2 :(得分:0)
你想要实现的目标是:
function OBJ() {
this.id = 0;
this.arr = [0,0];
}
let obj1 = new OBJ();
let obj2 = new OBJ();
因为它为每个新创建的对象创建一个单独的实例,即每个新创建的对象都有自己的id和arr副本。
您的方法适用于原始数据类型,但不适用于像Array这样的非原始数据类型。您正在实例化原型上的数组,而没有意识到变异该数组将为所有实例修改它。
obj1 和 obj2 最初引用了OBJ原型的 id 和 arr 。
obj1 / obj2 只有在 obj1.id / obj2.id 发生更改时才有自己的 id 新副本,否则会引用与 OBJ 原型相同的 id 。
现在,此行为仅适用于基本类型。 对于非基本类型,即Array, obj1 和 obj2 始终引用OBJ原型的相同 arr 。