JavaScript深拷贝无绝对最优方案,需按场景选择:JSON.parse(JSON.stringify())适合纯数据对象;structuredClone()是现代浏览器首选,支持多种内置类型且自动处理循环引用;lodash.cloneDeep()兼顾兼容性与功能;手写递归+WeakMap适用于学习或定制需求。

JavaScript中没有“绝对最优”的深拷贝方案,只有最适配当前场景的解法。关键看是否需要兼容性、是否处理循环引用、是否保留特殊对象(如Date、RegExp、Map、Set等),以及性能要求。
JSON.parse(JSON.stringify()) —— 简单场景够用
适合纯数据对象(Plain Object)和数组,且不包含函数、undefined、Symbol、BigInt、Date、RegExp、循环引用等。
- 优点:原生、无依赖、速度快
- 缺点:会丢失函数、undefined、Symbol;Date 变成字符串;NaN 变成 null;无法处理循环引用,直接报错
const obj = { a: 1, b: [2, 3], c: new Date() };<br>const copy = JSON.parse(JSON.stringify(obj)); // c 变成 ISO 字符串,函数和 undefined 全丢失
structuredClone() —— 现代浏览器推荐首选
Chrome 98+、Firefox 94+、Safari 15.4+ 已支持,是目前最接近“标准最优解”的原生方法。
立即学习“Java免费学习笔记(深入)”;
- 支持 Map、Set、Date、RegExp、ArrayBuffer、TypedArray、Error、Blob、FormData 等大多数内置类型
- 自动处理循环引用(不报错)
- 不支持函数、undefined、Symbol(和 structuredClone 规范一致)
const copy = structuredClone(originalObj);
若需兼容旧环境,可配合 feature detection + 回退方案(如 lodash.cloneDeep)。
lodash.cloneDeep() —— 兼容性与功能平衡之选
在 Node.js 或需支持 IE/老版浏览器的项目中仍是主流选择。
- 支持函数、Date、RegExp、Map、Set、Uint8Array 等绝大多数类型
- 正确处理循环引用
- 体积稍大(约 70KB gzip 前),但按需引入(如只 import cloneDeep)可优化
npm install lodash.clonedeep<br>// ES Module<br>import cloneDeep from 'lodash.clonedeep';<br>const copy = cloneDeep(originalObj);
手写递归 + WeakMap 处理循环引用 —— 理解原理或定制需求
适合学习、轻量定制(如只深拷贝特定类型),或避免引入第三方库。
- 核心思路:用 WeakMap 缓存已拷贝的对象,遇到重复引用直接返回缓存结果
- 需手动判断类型(Array、Date、RegExp、Object 等),并分别处理
- 不推荐在生产环境从零手写,除非有极强控制需求(如过滤某些字段、转换值)
function deepClone(obj, cache = new WeakMap()) {<br> if (obj === null || typeof obj !== 'object') return obj;<br> if (cache.has(obj)) return cache.get(obj);<br> const cloned = Array.isArray(obj) ? [] : {};<br> cache.set(obj, cloned);<br> for (let key in obj) {<br> if (Object.prototype.hasOwnProperty.call(obj, key)) {<br> cloned[key] = deepClone(obj[key], cache);<br> }<br> }<br> return cloned;<br>}
注意:该版本未处理 Date、RegExp、Map、Set 等,仅作逻辑示意。


















