浅拷贝只复制第一层引用,Object.assign和展开运算符最常用;深拷贝需递归处理,JSON方法快但限制多,structuredClone更可靠但有兼容性要求,lodash.cloneDeep功能全但体积大。

浅拷贝只复制第一层引用,Object.assign 和展开运算符最常用
浅拷贝不会递归复制嵌套对象,只是把顶层属性的值(如果是引用类型)复制一份新指针。这意味着修改嵌套对象的属性,原对象和拷贝对象会互相影响。
常见写法:
-
Object.assign({}, obj):适用于普通对象,不处理null或undefined作为源 -
{...obj}:ES6+ 更简洁,但同样只展开一层,且不能拷贝不可枚举属性、Symbol键或原型链上的属性 -
Array.prototype.slice()或[...arr]:数组浅拷贝,对嵌套数组无效
注意:Object.assign 会跳过 undefined 源对象,但不会报错;如果目标对象有 setter,可能触发副作用。
深拷贝要递归处理所有层级,JSON.parse(JSON.stringify()) 最快但限制多
这个组合在多数简单场景下够用,执行快、写法短,但它根本无法处理以下情况:
立即学习“Java免费学习笔记(深入)”;
-
undefined、function、Symbol、BigInt会被忽略或报错 - 循环引用直接抛出
TypeError: Converting circular structure to JSON - Date、RegExp、Map、Set、TypedArray 等对象变成空对象或丢失类型
- 原型链和不可枚举属性全部丢失
所以它只适合「纯数据对象」——即只含字符串、数字、布尔、null、普通对象和数组的结构。
需要可靠深拷贝时,用 structuredClone(现代浏览器)或手写递归函数
structuredClone 是目前最接近“开箱即用”的标准方案,支持 Date、RegExp、Map、Set、ArrayBuffer 等,也支持循环引用,但仍有边界:
- 不支持
function、undefined、Symbol、Promise、Window等宿主对象 - Node.js 17+ 才默认启用,旧版需加
--experimental-structured-cloning - 浏览器兼容性:Chrome 98+、Firefox 94+、Safari 15.4+,IE 完全不支持
若需兼容更老环境或定制行为(比如跳过某些字段、转换日期格式),就得手写递归函数。关键点是:必须用 Map 记录已访问对象来处理循环引用,否则栈溢出;区分 Array、Date、RegExp 等类型并分别构造新实例。
第三方库如 lodash.cloneDeep 稳定但引入体积大
lodash.cloneDeep 覆盖场景最广,能处理函数(拷贝为 undefined)、Map/Set、稀疏数组、甚至部分 DOM 节点(取决于版本)。但它不是零依赖:压缩后约 10KB,对轻量项目可能是负担。
使用前确认是否真需要它支持的所有类型——比如项目里压根没 Map 或循环引用,那 structuredClone 或改良版 JSON 方案就更轻量。
另外,别在热路径(如每帧调用)中无节制深拷贝大对象,性能损耗明显;考虑用不可变更新(immer)或状态分片来规避。











