【问题标题】:How spread syntax in object works?对象中的扩展语法如何工作?
【发布时间】:2018-11-05 23:44:48
【问题描述】:

遇到了使用扩展语法创建新对象的概念,如下所示

const human = { age: 20 };
const john = { ...human };
john.age = 10;
console.log(human.age); // 20
console.log(john.age); // 10

如上图所示,人类对象得到保留它的原始值。现在看看下面的代码:

const human = { age: 20, cars: ["toyota", "honda"] };
const john = { ...human };
john.cars[1] = "camero";
console.log(human.cars); // ["toyota", "camero"]
console.log(john.cars); // ["toyota", "camero"]

谁能向我解释为什么会发生上述情况?为什么人类的汽车对象会改变?在我看来,开发人员很可能在不了解如何避免不一致行为的情况下犯错误

【问题讨论】:

    标签: javascript ecmascript-6 spread-syntax


    【解决方案1】:

    对象human 仅包含对包含["toyota", "honda"] 的数组的引用。当您使用扩展运算符复制对象时,您也复制了 reference,这意味着 john 具有相同的引用,因此 john.carshuman.cars 是同一个数组。

    因此,如果你修改john.cars,你也会修改human.cars,因为它们是同一个数组。如果你想克隆一个数组,你也可以使用扩展运算符来做到这一点:

    const human = { age: 20, cars: ["toyota", "honda"] };
    const john = { ...human };
    john.cars = [ ... human.cars ];
    john.cars[1] = "camero";
    console.log(human.cars); // ["toyota", "honda"]
    console.log(john.cars); // ["toyota", "camero"]

    如果你克隆一个具有对象属性的对象,你也会看到这种行为:

    const human = { name: { first: "John", last: "Jackson" } };
    const human2 = { ... human };
    
    human2.name.first = "Ellen";
    
    console.log(human.name.first); // Ellen

    这是因为展开运算符仅将 reference 复制到名称对象,而不是名称对象本身。因此,修改一个会修改另一个,因为它们是同一个对象。这称为浅克隆。如果您想避免这种混淆,您需要执行深度克隆

    最简单的方法是先转换成 JSON,然后再转换回来:

    const human = { name: { first: "John", last: "Jackson" } };
    const human2 = JSON.parse(JSON.stringify(human));
    
    human2.name.first = "Ellen";
    
    console.log(human.name.first); // John
    console.log(human2.name.first); // Ellen

    【讨论】:

    • 如果你说对象human 只包含对数组["toyota","honda"] 的引用,那么我可以知道这个数组在哪里吗?不参考human怎么能参考?
    • @Isaac 你不能。这是 JavaScript,不是 C++;您无法获得指向内存的指针。如果您将human.cars 分配给其他东西,并且您没有在不同的变量中进行其他引用,那么将没有其他方法可以访问该数组,它将被自动删除。
    • 您可能应该说... 是文本开头的浅层克隆。这是主要原因。
    猜你喜欢
    • 2017-06-23
    • 2018-06-13
    • 2019-08-26
    • 2013-01-01
    • 2017-10-12
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    相关资源
    最近更新 更多