浅拷贝仅复制对象本身及基本类型值,引用类型共享同一底层对象;深拷贝递归复制所有层级,包括引用类型实际内容,新旧对象完全独立。

浅拷贝只复制对象本身和基本类型字段的值,引用类型字段仅复制地址,新旧对象共享同一底层对象;深拷贝则递归复制所有层级,包括引用类型指向的实际内容,新旧对象完全独立。
核心区别:就看引用类型怎么处理
关键不在“拷不拷”,而在“怎么拷引用类型”:
- 浅拷贝:对引用类型,只把指针(内存地址)复制一份,新对象和原对象的该字段仍指向堆中同一个对象
- 深拷贝:对引用类型,会新建一个一模一样的对象,把原对象里引用字段所指的内容也完整复制一遍,两个对象互不干扰
- 基本类型(int、boolean、String等)无论浅拷还是深拷,都是直接复制值,这点没区别
常见实现方式(按语言场景)
不同语言有惯用法,但逻辑一致:
- JavaScript:浅拷贝可用Object.assign({}, obj)、展开运算符{...obj}、Array.from(arr);深拷贝常用JSON.parse(JSON.stringify(obj))(限制多)或递归函数/structuredClone(现代环境)
- Java:浅拷贝靠clone()(需实现Cloneable);深拷贝可手动重写clone()并逐个克隆引用字段,或用序列化+反序列化
- Python:浅拷贝用copy.copy()或切片list[:];深拷贝必须用copy.deepcopy()
- C++:默认拷贝构造函数和赋值运算符是浅拷贝;若类含指针,须自定义深拷贝逻辑(分配新内存 + 逐字节复制)
什么时候容易踩坑?
问题通常出在“以为拷了,其实没真隔离”:
- 修改浅拷贝后的对象中某个数组元素,原对象数组跟着变——因为数组是引用类型,只拷了地址
- 前端表单编辑时,用展开运算符复制带嵌套对象的数据,提交前改了子项,结果原数据源也被污染
- Java中用clone()后没重写引用字段的克隆逻辑,导致两个对象共用同一个ArrayList实例
- JSON深拷贝失效:遇到undefined、function、Date、RegExp、循环引用时直接丢弃或报错
怎么选?看需求是否需要“彻底断联”
没有绝对好坏,只有适不适合:
- 要快速备份结构、且确定后续只读或只改基本字段 → 浅拷贝够用,省资源
- 要传参给可能修改内部状态的方法、做多线程副本、或作为模板反复生成独立实例 → 必须深拷贝
- 不确定嵌套深度或含特殊类型?优先用语言提供的可靠深拷贝方案(如Java序列化、Python deepcopy、JS structuredClone),别手写简易版

















