首页 > 解决方案 > 对象中的扩展语法如何工作?

问题描述

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

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

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

标签: javascriptecmascript-6spread-syntax

解决方案


该对象human仅包含包含["toyota", "honda"]. 当您使用扩展运算符复制对象时,您也复制了引用,这意味着john具有相同的引用,因此john.cars与 相同的数组human.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

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

最简单的方法是转换为 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


推荐阅读