javascript 为什么 2 个不同的对象引用 to/using 同一个数组?

javascript why 2 different object are refering to/using same array?

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

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

应该是你想要的,它会递归复制所有内容

问题

当您使用 Object.create() to create an new object from OBJ, OBJ becomes the prototype of the new object. All methods and properties are taken from the prototype chain 时,除非对象通过拥有自己的同名属性来覆盖它们。由于 arrOBJ 的 属性,所有对象都会更新,并显示相同的数组。

建议的解决方案

您可以将 arr 转换为 getter that will check if arr is a property of the current object using Object.hasOwnProperty(),如果不能,请克隆原型数组,然后 return 它。

//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]

您想要实现的目标可以通过以下方式实现:

function OBJ() {
    this.id = 0;
    this.arr = [0,0];
}

let obj1 = new OBJ();    
let obj2 = new OBJ(); 

因为它为每个新创建的对象创建一个单独的实例,即每个新创建的对象都有自己的 id 和 arr 副本。


您的方法适用于原始数据类型,但不适用于非原始数据类型,例如 Array.You 在原型上实例化一个数组,但没有意识到改变该数组会为所有实例修改它。

obj1obj2 最初引用相同的 idarr 的 OBJ 原型。

obj1 / obj2 只有在 obj1.id / obj2.id被改变了,否则它们指的是与OBJ的原型相同的id

现在,此行为仅适用于原始类型。 对于非基本类型,即 Array , obj1obj2 总是引用相同的 arr OBJ原型。