为什么更改复制数组中的对象也会影响原始对象呢?

时间:2020-04-25 16:25:30

标签: javascript reactjs ecmascript-6

在这段代码中,我使用传播运算符将obj复制到copiedObj中。然后将checked属性值修改为false。但是,当我console.log(obj.checked[0])时,它返回false而不是true。并且似乎checked中的copiedObj值也更改了原始属性值。这是为什么?

const obj = [{id: 1, checked: true}];
const copiedObj = [...obj];
copiedObj.checked[0] = false;
console.log(obj.checked[0]);

3 个答案:

答案 0 :(得分:5)

System.InvalidOperationException - A method was called at an unexpected time. obj是数组,而不是普通对象。更改copiedObj的状态(通过向其添加copiedObj属性)不会更改checked的状态,因为它们是独立的数组。

但是,两个数组都包含对相同对象(上面带有obj的对象)的引用。因此,如果您这样做:

cheecked

这将更改该对象的状态,您将看到在checkedObj[0].checked = true; obj[0]上查找该对象。

如果要进行深层复制,以便具有单独的数组独立的对象,请参见this question's answers

由于我99%确信您的意思是checkedObj[0],所以我将解释这段代码中发生的事情:

checkedObj[0].checked = true

逐步:

之后

// Creates an array containing an object
const obj = [{id: 1, checked: true}];
// Creates a new array that contains the *same* object (NOT a *copy* of it)
const copiedObj = [...obj];
// Sets `checked` on that one object that is in both arrays
copiedObj[0].checked = false;
// Looks at the `checked` property on that one object that is in both arrays
console.log(obj[0].checked);

在内存中您有类似的东西

                  +−−−−−−−−−−−−−+
obj:Ref44329−−−−−>|   (array)   |
                  +−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−+
                  | 0: Ref82445 |−−−>|   (object)    |
                  +−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−+
                                     | id: 1         |
                                     | checked: true |
                                     +−−−−−−−−−−−−−−−+

那么当你做

// Creates an array containing an object
const obj = [{id: 1, checked: true}];

你有类似的东西:

                       +−−−−−−−−−−−−−+
obj:Ref44329−−−−−−−−−−>|   (array)   |
                       +−−−−−−−−−−−−−+   
                       | 0: Ref82445 |−−+
                       +−−−−−−−−−−−−−+  |
                                        |
                                        |   +−−−−−−−−−−−−−−−−+
                                        +−−>|   (object)     |
                       +−−−−−−−−−−−−−+  |   +−−−−−−−−−−−−−−−−+
checkedObj:Ref12987−−−>|   (array)   |  |   | id: 1          |
                       +−−−−−−−−−−−−−+  |   | checked: true  |
                       | 0: Ref82445 |−−+   +−−−−−−−−−−−−−−−−+
                       +−−−−−−−−−−−−−+ 

那么当你做

// Creates a new array that contains the *same* object (NOT a *copy* of it)
const copiedObj = [...obj];

它更改两个数组都指向的对象

                       +−−−−−−−−−−−−−+
obj:Ref44329−−−−−−−−−−>|   (array)   |
                       +−−−−−−−−−−−−−+   
                       | 0: Ref82445 |−−+
                       +−−−−−−−−−−−−−+  |
                                        |
                                        |   +−−−−−−−−−−−−−−−−+
                                        +−−>|   (object)     |
                       +−−−−−−−−−−−−−+  |   +−−−−−−−−−−−−−−−−+
checkedObj:Ref12987−−−>|   (array)   |  |   | id: 1          |
                       +−−−−−−−−−−−−−+  |   | checked: false |
                       | 0: Ref82445 |−−+   +−−−−−−−−−−−−−−−−+
                       +−−−−−−−−−−−−−+

...因此,无论您通过哪个数组查看它,查找它都会得到// Sets `checked` on that one object that is in both arrays copiedObj[0].checked = false;

答案 1 :(得分:1)

obj是对象的数组,当您这样做时:

const copiedObj = [...obj];

您创建了一个新数组,但是在该数组中,您仍将引用obj

中的对象

之所以发生这种情况,是因为您有两个级别:数组->对象,但是散布运算符仅适用于第一级别(数组)

答案 2 :(得分:1)

这是因为,当您由散布运算符创建copiedObj时,仍在引用最初在内存中创建的对象。

为了解决此问题,以便获得预期的行为,还创建对象内部所有属性的另一个浅表副本。

p.s。我修改了copiedObj[0].checked = false; console.log(obj[0].checked),因为我认为您正在尝试选择创建的数组中的第一个元素。

const obj = [{id: 1, checked: true}];
const copiedObj = [Object.assign({}, obj[0])];
copiedObj[0].checked = false;
console.log(obj[0].checked)
//returns true