【问题标题】:Why does changing object in copied array also affects the object from original one?为什么更改复制数组中的对象也会影响原始对象?
【发布时间】:2020-08-09 05:39:49
【问题描述】:

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

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

【问题讨论】:

  • obj 是一个包含单个对象的数组。 copiedObj 是另一个包含相同对象的数组。您正在复制数组,而不是对象。如果要深度复制数组中的对象,请执行copiedObj = [...{obj[0]}]。但实际上,这些变量应该是arrcopiedArr 以避免混淆。
  • 我怀疑你的意思是checkedObj[0].checked = true,对吧?
  • copiedObj.checked[0] = false => copiedObj[0].checkedobj.checked[0] => obj[0].checked,对吧?

标签: javascript reactjs ecmascript-6


【解决方案1】:

obj 是一个对象数组,当你这样做时:

const copiedObj = [...obj];

您创建了一个新数组,但在该数组中您仍将引用来自 obj 的对象

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

【讨论】:

    【解决方案2】:

    objcopiedObj 是数组,而不是普通对象。更改 copiedObj 的状态(通过向其添加 checked 属性)不会更改 obj 的状态,因为它们是单独的数组。

    但是,两个数组都包含对同一个对象(带有cheecked 的那个)的引用。所以如果你这样做了:

    checkedObj[0].checked = true;
    

    这将改变那个对象的状态,无论你是在obj[0] 还是checkedObj[0] 上查找该对象,你都会看到这一点。

    如果您想进行深层复制以便拥有单独的数组单独的对象,请参阅this question's answers

    由于我 99% 确定您的意思是 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);

    一步一步:

    之后

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

    在内存中你有类似的东西

    +−−−−−−−−−−−−−−+ obj:Ref44329−−−−−>| (数组) | +−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | 0: Ref82445 |−−−>| (对象) | +−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ |编号:1 | |检查:真| +−−−−−−−−−−−−−−−−−+

    那么当你这样做时

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

    你有类似的东西:

    +−−−−−−−−−−−−−−+ obj:Ref44329−−−−−−−−−−−>| (数组) | +−−−−−−−−−−−−−−+ | 0: Ref82445 |−−+ +−−−−−−−−−−−−−−+ | | | +−−−−−−−−−−−−−−−−−−+ +−−>| (对象) | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−+ checkedObj:Ref12987−−−>| (数组) | | |编号:1 | +−−−−−−−−−−−−−+ | |检查:真| | 0: Ref82445 |−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+

    那么当你这样做时

    // Sets `checked` on that one object that is in both arrays
    copiedObj[0].checked = false;
    

    它改变了两个数组指向的对象

    +−−−−−−−−−−−−−−+ obj:Ref44329−−−−−−−−−−−>| (数组) | +−−−−−−−−−−−−−−+ | 0: Ref82445 |−−+ +−−−−−−−−−−−−−−+ | | | +−−−−−−−−−−−−−−−−−−+ +−−>| (对象) | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−−+ checkedObj:Ref12987−−−>| (数组) | | |编号:1 | +−−−−−−−−−−−−−−+ | | 检查:假 | | 0: Ref82445 |−−+ +−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+

    ...所以无论您通过哪个数组查看它,查找它都会给您false

    【讨论】:

    • 感谢您提供如此详细的图表答案!我还根据您的评论更改了我的问题。
    【解决方案3】:

    这是因为当您通过扩展运算符创建 copiedObj 时,您仍在引用最初在内存中创建的对象。

    为了解决这个问题,您将获得预期的行为是创建对象内所有属性的另一个浅表副本。

    附言我修改了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
    

    【讨论】:

      猜你喜欢
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-22
      • 2021-04-01
      • 2018-07-24
      • 2016-01-10
      相关资源
      最近更新 更多