JavaScript扩展运算符为何表现不同?嵌套与普通属性差异解析
对象浅拷贝导致的属性修改差异解析
先看你给出的代码和输出:
const x = { name: "ABC", email: "ac@gmail.com", mob: "12345", address: { city: "Mumbai", state: "Maharastra" } }; const y = { ...x } x.name = "XYZ"; console.log(x.name, y.name); x.address.city = "Pune"; console.log(x.address.city, y.address.city);
输出:
XYZ ABC Pune Pune
核心原因:浅拷贝的特性
你用{ ...x }这种扩展运算符实现的对象复制是浅拷贝,它对对象属性的处理分两种情况:
- 基本数据类型属性(如name、email、mob):这类属性的值是直接存在栈内存里的原始值,浅拷贝会把值完整复制一份给新对象y。所以x和y的name属性是完全独立的两个值,修改x.name只会改变x自己的属性值,不会影响y.name。
- 引用数据类型属性(如address):这类属性存储的不是实际对象内容,而是指向堆内存中对象的引用地址。浅拷贝只会把这个引用地址复制给y的address属性,也就是说x.address和y.address指向的是堆内存里的同一个对象。所以当你修改
x.address.city时,本质是在修改堆内存里那个共享对象的属性,x和y的address都指向这个对象,自然都会看到city变成了Pune。
如果想要让y的address和x完全独立,需要用到深拷贝,比如可以用JSON.parse(JSON.stringify(x))(注意这种方法有局限性,无法处理函数、Symbol等特殊类型),或者手动递归复制嵌套对象。
内容的提问来源于stack exchange,提问作者Ramanjeet
相关产品推荐
相关产品推荐

