浅拷贝仅复制第一层属性,嵌套引用仍共享内存;object.assign()、展开运算符、slice()等均属浅拷贝;json.parse(json.stringify())看似深拷贝实则丢失函数/date/map等且不支持循环引用;可靠方案为structuredclone()(现代浏览器)、lodash.clonedeep(全兼容)或手写递归(需weakmap防循环)。

JavaScript 中对象的深拷贝,核心是创建一个与原对象完全独立的新对象,所有嵌套层级(包括对象、数组、日期、正则等)都重新分配内存,修改副本不会影响原始数据。浅拷贝只复制第一层属性,嵌套引用仍共享地址——这是多数“改了副本,原对象也变”问题的根源。
哪些方法属于浅拷贝?
这些方式速度快、开销小,但仅适用于确定无嵌套或仅需顶层隔离的场景:
-
Object.assign({}, obj):只拷贝可枚举自有属性,
obj.b.c = 10会同步影响原对象 -
展开运算符 {obj}:语法简洁,行为与
Object.assign一致 - Array.prototype.slice() / Array.from() / [...arr]:对数组有效,但内部对象仍共用引用
JSON.parse(JSON.stringify()) 能不能当深拷贝用?
它能快速实现“看起来像深拷贝”的效果,但有明显硬伤,**不建议用于生产环境**:
- 函数、
undefined、Symbol、BigInt直接丢失 -
Date变成字符串,RegExp变成空对象,Map/Set无法保留 - 遇到循环引用立即报错:
TypeError: Converting circular structure to JSON - NaN → null,Infinity → null,原型链和不可枚举属性全部丢失
真正可靠的深拷贝方案有哪些?
根据项目需求和运行环境选择:
-
structuredClone():浏览器原生 API(Chrome 98+、Firefox 94+、Safari 15.4+),支持
Date、Map、Set、RegExp、ArrayBuffer等,也处理循环引用,但暂不支持函数和undefined - Lodash 的 cloneDeep():最稳妥的通用方案,覆盖几乎所有类型(含函数、Symbol、循环引用、原型),兼容性好,适合中大型项目
-
手写递归函数:需手动判断类型(
Array.isArray、instanceof Date)、用WeakMap缓存已拷贝对象防死循环、区分Object.keys()和继承属性;适合学习原理或极简依赖场景
实际开发怎么选?
简单配置数据、API 响应体且不含特殊类型 → structuredClone() 或 JSON 方案;业务逻辑复杂、需兼容老环境、含函数/Map/Set/循环引用 → 直接上 lodash.cloneDeep;想控制细节或做轻量工具库 → 手写并重点处理 WeakMap 缓存和内置对象构造逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











