浅拷贝只复制第一层引用,深拷贝递归复制所有层级;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: "2023-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 等,且支持循环引用:
立即学习“Java免费学习笔记(深入)”;
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的限制,但明确报错而非静默丢弃) - Node.js 17.0+ 需启用
--experimental-structured-cloning标志,18.15+ 默认启用 - 若需兼容老环境,手写递归函数必须显式判断
Array.isArray()、obj.constructor === Date等类型,并用WeakMap记录已遍历对象以解决循环引用
真正复杂的数据结构深拷贝没有银弹——structuredClone() 覆盖大多数场景,但一旦涉及函数序列化或自定义类实例,就得按需定制逻辑。











