javascript为什么2个不同的对象引用/使用相同的数组?

时间:2018-04-27 05:07:24

标签: javascript arrays object members

我有一个包含数组的对象定义。当我实例化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]

3 个答案:

答案 0 :(得分:0)

https://lodash.com/docs/4.17.5#cloneDeep

应该是你想要的,它将以递归的方式复制所有内容

答案 1 :(得分:0)

<强>问题

当您使用Object.create()OBJ创建新对象时,OBJ将成为新对象的原型。所有方法和属性都取自prototype chain,除非该对象具有自己的同名属性,否则会覆盖它们。由于arrOBJ的属性,因此所有对象都会更新,并显示相同的数组。

建议的解决方案

您可以将arr转换为getter,使用Object.hasOwnProperty()检查arr是否是当前对象的属性,如果不是,则克隆原型数组,然后归还。

&#13;
&#13;
//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;
&#13;
&#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