浅拷贝只复制第一层引用,深拷贝递归复制所有层级;Object.assign()和展开运算符是浅拷贝,JSON.stringify()有诸多限制,structuredClone()是现代可靠方案但不支持函数等类型。
JavaScript 中对象和数组是引用类型,直接赋值只是复制了内存地址。浅拷贝只断开最外层的引用,内部嵌套的对象/数组仍共享;深拷贝则确保新对象与原对象完全独立,修改任意一层都不会互相影响。
Object.assign() 和展开运算符 ... 是典型浅拷贝它们只处理对象自身可枚举属性,且仅拷贝第一层:
const a = { x: 1, y: { z: 2 } };
const b = { ...a };
b.y.z = 99;
console.log(a.y.z); // 99 —— 被意外修改
Object.assign({}, obj) 不处理 null 或 undefined 源对象Map、Set、Date、RegExp 等无效,会丢失类型和原型Symbol 属性时,Object.assign() 会拷贝,但展开运算符不会JSON.parse(JSON.stringify()) 是有缺陷的“伪深拷贝”它能处理多层嵌套,但存在多个硬性限制:
const obj = { a: 1, b: () => {}, c: undefined, d: Symbol('x'), e: new Date(), f: /abc/ };
const copy = JSON.parse(JSON.stringify(obj));
// 结果:{ a: 1, e: "2025-01-01T00:00:00.000Z" } —— 其余全丢失
undefined、Symbol、BigInt 会被静默丢弃Date 变成字符串,RegExp 变成空对象,Map/Set 变成空对象TypeError: Converting circular structure to JSON
structuredClone() 或手写递归函数
structuredClone() 是现代浏览器(Chrome 98+、Firefox 94+、Safari 16.4+)原生支持的方案,能正确处理 Date、RegExp、Map、Set、ArrayBuffer 等,且支持循环引用:
const obj = { a: new Date(), b: new Map([[1, 'x']]) };
const copy = structuredClone(obj);
copy.a.setFullYear(2050);
console.log(obj.a.getFullYear()); // 仍是原年份
undefined、Symbol、BigInt(同 JSON.stringify 的限制,但明确报错而非静默丢弃)--experimental-structured-cloning 标志,18.15+ 默认启用Array.isArray()、obj.constructor === Date 等类型,并用 WeakMap 记录已遍历对象以解决循环引用真正复杂的数据结构深拷贝没有银弹——structuredClone() 覆盖大多数场景,但一旦涉及函数序列化或自定义类实例,就得按需定制逻辑。