javascript - 对象中的扩展语法如何工作?
问题描述
遇到了使用扩展语法创建新对象的概念,如下所示
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"]
. 当您使用扩展运算符复制对象时,您也复制了引用,这意味着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
推荐阅读
- javascript - 获取 flexbox 定位元素的左侧和顶部
- android - 带有 Crosswalk 的 Ionic 应用程序编译、安装但无法打开
- r - 基于多个变量过滤数据
- c - 查找字符串中数字(0-9)的频率
- actionscript-3 - Nape Physics:碰撞问题(跨瓷砖移动)
- python - python os.path.exists 返回 false
- ruby-on-rails - 如何解析has_many关联before_save
- python-2.7 - Jython 2.7.1 + ftfy 4.4
- excel - 如何将范围数据导入 VBA?
- wpf - WPF 可重用标签和文本框行