浅拷贝后修改引用类型内部属性会改变原对象,因其仅复制第一层结构,嵌套引用类型仍共享堆内存地址;如{...obj}拷贝后改obj.nested.prop,原对象同步变化。

浅拷贝后修改引用类型的内部属性会引发副作用,根本原因在于:它只复制了对象第一层的结构,而嵌套的引用类型值(如对象、数组、日期等)仍指向同一块堆内存。
浅拷贝的本质是“复制地址,不复制对象”
当你用 Object.assign({}, obj)、{...obj} 或 arr.slice() 做浅拷贝时:
- 对基本类型(number、string、boolean 等),拷贝的是实际值,彼此独立
- 对引用类型(如
obj.nested是一个对象),拷贝的只是该对象在堆中的内存地址(比如0x7a1f) - 新旧对象的对应字段,指向堆中同一个实例——就像两个人共用一把钥匙开同一扇门
副作用怎么发生的?看一个典型例子
执行以下代码:
const user = { name: "Alice", profile: { age: 30, city: "Beijing" } };
const copy = { ...user };
copy.profile.age = 35;
console.log(user.profile.age); // 输出 35 —— 原对象被意外改了
这里 copy.profile 和 user.profile 指向同一个子对象。改 copy.profile.age,就是在堆里直接操作那个共享对象,所以 user 也同步变化。
哪些操作属于“改内部属性”,会触发副作用?
只要没改变变量本身的指向,而是通过点号(.)、中括号([])或方法(如 push、add)去操作对象/数组的内容,就属于这类:
-
copy.items.push("new")→ 原数组items多了一项 -
copy.config.enabled = false→ 原config对象的enabled变了 -
copy.matrix[0][1] = 99→ 若matrix[0]是共享的数组,原二维结构也被污染
什么操作不会影响原对象?
只有重赋值操作会让形参或副本变量“换锁匙”,不再指向原对象:
-
copy.profile = { age: 40 };→copy.profile指向新对象,user.profile不变 -
copy = { name: "Bob" };→ 整个copy变量换了引用,和user彻底无关
副作用不是语言缺陷,而是引用语义的自然结果。关键不在“怎么传”,而在“改什么”——动的是内容,还是变量本身。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











