|
到现在为止,我们都假设 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 才会报错。
也就是说,如果我们真的需要创建常量对象属性,也是可以的,但使用的是完全不同的方法。我们将在 属性标志和属性描述符 一章中学习它。
|
|