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 时,除非对象通过拥有自己的同名属性来覆盖它们。由于 arr
是 OBJ
的 属性,所有对象都会更新,并显示相同的数组。
建议的解决方案
您可以将 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 在原型上实例化一个数组,但没有意识到改变该数组会为所有实例修改它。
obj1 和 obj2 最初引用相同的 id 和 arr 的 OBJ 原型。
obj1 / obj2 只有在 obj1.id / obj2.id被改变了,否则它们指的是与OBJ的原型相同的id。
现在,此行为仅适用于原始类型。
对于非基本类型,即 Array , obj1 和 obj2 总是引用相同的 arr OBJ原型。
我有一个对象定义,其中有一个数组。当我实例化 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 时,除非对象通过拥有自己的同名属性来覆盖它们。由于 arr
是 OBJ
的 属性,所有对象都会更新,并显示相同的数组。
建议的解决方案
您可以将 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 在原型上实例化一个数组,但没有意识到改变该数组会为所有实例修改它。
obj1 和 obj2 最初引用相同的 id 和 arr 的 OBJ 原型。
obj1 / obj2 只有在 obj1.id / obj2.id被改变了,否则它们指的是与OBJ的原型相同的id。
现在,此行为仅适用于原始类型。 对于非基本类型,即 Array , obj1 和 obj2 总是引用相同的 arr OBJ原型。