浅拷贝只复制第一层属性,引用类型共享堆内存地址;深拷贝递归复制所有层级,在堆中为每个嵌套对象创建独立副本,新旧对象完全隔离。

浅拷贝和深拷贝在引用类型中的区别,本质是看堆内存里有没有“多盖一栋楼”——不是代码写了多少行,而是运行时两个对象是否真的各自占了一块独立的堆空间。
栈里只存“门牌号”,堆里才住着真数据
当你声明 const obj = { name: '张三', address: { city: '杭州' } } 时:
- 栈内存中,obj 存的是一个地址(比如 0x1a2b);
- 堆内存中,0x1a2b 指向的实际位置放着 { name: '张三', address: {...} };
- 而 address 这个属性本身又是引用类型,它在堆里另有地址(比如 0x3c4d),指向 { city: '杭州' } 这个子对象。
浅拷贝:只配一把新钥匙,开同一扇门
像 {...obj}、Object.assign({}, obj) 或 Array.prototype.slice() 这些操作:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 会在栈里新建一个变量(比如 copy),也给它分配一个新地址(如 0x5e6f);
- 然后把 obj 第一层的每个属性值“抄过去”:
—— name: '张三' 是基本类型,就真复制一份字符串;
—— address 是引用,只把 0x3c4d 这个地址原样抄过去; - 结果是:copy.address 和 obj.address 指向堆中同一个 0x3c4d 地址,改 copy.address.city 就等于直接改那间房子里的东西。
深拷贝:每间房都重盖一遍,互不串门
像 JSON.parse(JSON.stringify(obj))(简单场景)、structuredClone()(现代浏览器)、或手写递归函数:
立即学习“Java免费学习笔记(深入)”;
- 先在堆里为 copy 分配新地址(0x7g8h),再把 name 的值复制进去;
- 发现 address 是对象,就暂停,再去堆里另分一块地(比如 0x9i0j),把 { city: '杭州' } 完整重建进去;
- 如果 address 里还有对象,继续往下挖——每一层引用都新开堆空间,最终所有嵌套结构都有自己的物理位置;
- 修改 copy.address.city,只动 0x9i0j 这块地,对 0x3c4d 完全没影响。
怎么验证是不是真深拷贝?
别光看代码长得像不像,打开浏览器的开发者工具 → Memory 面板,做一次快照对比:
- 拷贝前拍一张,记下对象占用的堆内存块;
- 拷贝后再拍一张,如果新增了对应数量和结构的独立内存块,才是真正的深拷贝;
- 如果只多了一个外层对象,内部嵌套还共用旧地址,那就是浅拷贝——哪怕你用了 lodash.cloneDeep,也要小心循环引用或特殊类型(如 Date、RegExp)没被正确处理。

















