对象中的传播语法如何工作?
How spread syntax in object works?
遇到了使用扩展语法创建新对象的概念,如下所示
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"]
谁能给我解释一下为什么会出现上述情况?为什么人类的汽车对象会发生变化?在我看来,开发人员很可能在不了解如何避免不一致行为的情况下犯错误
对象 human
仅包含对包含 ["toyota", "honda"]
的数组的 引用 。当您使用扩展运算符复制对象时,您还复制了 reference,这意味着 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
那是因为展开运算符只复制一个reference到name对象,而不是name对象本身。因此,修改一个也会修改另一个,因为它们是同一个对象。这被称为浅克隆。如果你想避免这种混淆,你需要执行一个深度克隆。
最简单的方法是转换为 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
遇到了使用扩展语法创建新对象的概念,如下所示
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"]
谁能给我解释一下为什么会出现上述情况?为什么人类的汽车对象会发生变化?在我看来,开发人员很可能在不了解如何避免不一致行为的情况下犯错误
对象 human
仅包含对包含 ["toyota", "honda"]
的数组的 引用 。当您使用扩展运算符复制对象时,您还复制了 reference,这意味着 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
那是因为展开运算符只复制一个reference到name对象,而不是name对象本身。因此,修改一个也会修改另一个,因为它们是同一个对象。这被称为浅克隆。如果你想避免这种混淆,你需要执行一个深度克隆。
最简单的方法是转换为 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