LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 585|回复: 0

深层克隆

[复制链接]
发表于 2024-2-19 23:02:52 | 显示全部楼层 |阅读模式
到现在为止,我们都假设 user 的所有属性均为原始类型。但属性可以是对其他对象的引用。

例如:

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

alert( user.sizes.height ); // 182
现在这样拷贝 clone.sizes = user.sizes 已经不足够了,因为 user.sizes 是个对象,它会以引用形式被拷贝。因此 clone 和 user 会共用一个 sizes:

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

let clone = Object.assign({}, user);

alert( user.sizes === clone.sizes ); // true,同一个对象

// user 和 clone 分享同一个 sizes
user.sizes.width++;       // 通过其中一个改变属性值
alert(clone.sizes.width); // 51,能从另外一个获取到变更后的结果
为了解决这个问题,并让 user 和 clone 成为两个真正独立的对象,我们应该使用一个拷贝循环来检查 user[key] 的每个值,如果它是一个对象,那么也复制它的结构。这就是所谓的“深拷贝”。

我们可以使用递归来实现它。或者为了不重复造轮子,采用现有的实现,例如 lodash 库的 _.cloneDeep(obj)。

使用 const 声明的对象也是可以被修改的
通过引用对对象进行存储的一个重要的副作用是声明为 const 的对象 可以 被修改。

例如:

const user = {
  name: "John"
};

user.name = "Pete"; // (*)

alert(user.name); // Pete
看起来 (*) 行的代码会触发一个错误,但实际并没有。user 的值是一个常量,它必须始终引用同一个对象,但该对象的属性可以被自由修改。

换句话说,只有当我们尝试将 user=... 作为一个整体进行赋值时,const user 才会报错。

也就是说,如果我们真的需要创建常量对象属性,也是可以的,但使用的是完全不同的方法。我们将在 属性标志和属性描述符 一章中学习它。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表