引用拷贝不创建新对象,仅复制引用地址,p1==p2为true,修改互相影响;浅拷贝创建新对象(p1==p2为false),但嵌套引用字段仍共享,修改子对象内容会相互影响。

浅拷贝和引用拷贝看似相似,但本质区别在于“是否创建新对象”。这个差异直接决定修改副本时原数据会不会被意外改动——业务逻辑错乱往往就发生在忽略这一点的时候。
引用拷贝:根本没创建新对象
只是把原变量的内存地址复制给了新变量,两者完全共享堆中同一块数据。改任何一个,另一个立刻同步变化,连对象身份(==)都为 true。
- Java 中:
Person p2 = p1; - JavaScript 中:
const obj2 = obj1; - 没有新实例,没有隔离性,纯属“起别名”
浅拷贝:创建了新对象,但嵌套引用仍共用
顶层对象是独立的(== 为 false),但内部的引用类型字段(如数组、子对象、StringBuilder)依然指向原对象的同一块堆内存。
- Java 中:
p2 = (Person) p1.clone();(需实现 Cloneable) - JavaScript 中:
const obj2 = {...obj1}或Object.assign({}, obj1) - 改基本类型字段互不影响;改嵌套对象/数组内容,双方都会变
关键判断点:看修改嵌套引用时原数据是否被动改变
这是验证你用的是浅拷贝还是引用拷贝最直接的方式:
- 如果
obj2.nested.name = "new"导致obj1.nested.name也变成 "new" → 是浅拷贝(或更糟:其实是引用拷贝) - 如果连
obj2 = obj1后改obj2.x都影响obj1.x→ 是引用拷贝,根本没拷贝 - 真正安全的浅拷贝必须满足:
obj1 !== obj2且obj1.topProp === obj2.topProp(对引用字段)
业务中高频踩坑场景
这些地方不区分二者,极易引发数据污染:
- 组件传参时直接把 props 对象赋值给内部 state(实为引用拷贝)
- 表单编辑前用
Object.assign处理嵌套对象,提交时发现原始数据已被修改 - 多线程/并发环境下,一个服务实例缓存了浅拷贝结果,多个请求并发修改其子对象
- 后端返回用户数据后,前端未深拷贝就传给多个模块处理,A 模块删了 address 字段,B 模块报空指针










