深拷贝必须在遍历前完成且彻底切断引用链;推荐structuredclone(现代环境)或手写递归+weakmap(旧环境),禁用json方案以防数据丢失。

遍历数组时做深拷贝,核心不是“边遍历边拷贝”,而是先完成深拷贝,再安全遍历;否则在 for、forEach 或 map 中直接修改原数组元素,仍可能污染源数据。关键在于:**拷贝动作必须在遍历开始前完成,且拷贝必须真正切断所有引用链**。
明确目标:为什么遍历时需要深拷贝
常见误区是以为用 forEach 或 for...of 遍历就能避免修改原数组——其实不然。如果数组里存的是对象,遍历时对 item.name = 'xxx' 这类操作,改的仍是原对象。深拷贝要确保:新数组里的每个对象,都是内存中独立的新实例。
推荐方案:优先用 structuredClone(现代环境)
适用于 Chrome 98+、Edge 99+、Firefox 94+、Safari 15.4+ 及 Node.js 17+:
- 一行搞定,自动处理 Date、RegExp、嵌套对象、循环引用
- 不支持函数、undefined、Symbol、WeakMap/WeakSet,但多数业务数据够用
- 代码简洁、性能好、无依赖
示例:
const original = [{ id: 1, user: { name: 'Alice' } }, { id: 2, user: { name: 'Bob' } }];
const safeCopy = structuredClone(original);
safeCopy.forEach(item => {
item.user.name += ' (copied)'; // 不影响 original
});
console.log(original[0].user.name); // 'Alice' —— 原数据未变
兼容旧环境:手写递归 + WeakMap 防循环引用
当需支持 IE 或老版 Node.js 时,自定义函数更可控:
- 用 WeakMap 记录已拷贝对象,避免无限递归
- 单独处理 Date、RegExp、Array、Object,跳过函数和 undefined
- 遍历前调用一次,得到完全隔离的副本
示例片段:
function deepClone(obj, seen = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (seen.has(obj)) return seen.get(obj);
const clone = Array.isArray(obj) ? [] : {};
seen.set(obj, clone);
for (const key in obj) {
if (Object.hasOwn(obj, key)) {
clone[key] = deepClone(obj[key], seen);
}
}
return clone;
}
const original = [{ config: { timeout: 3000 } }];
const copied = deepClone(original);
copied[0].config.timeout = 5000; // original 不变
慎用方案:JSON.parse(JSON.stringify())
仅适合纯数据场景(无 Date、正则、undefined、函数、Map/Set):
- 会把 Date 变成字符串,如 "2026-10-12T11:53:00.000Z"
- 丢弃 undefined、Symbol、函数,静默失败不易察觉
- 遇到循环引用直接报错,无法兜底
若确定数据结构干净,可临时使用:
const copied = JSON.parse(JSON.stringify(original));











