跳转到主内容
极星编程网:以代码为星,赴技术山海!

javascript深拷贝是什么_怎样实现对象的深度复制?

深拷贝是创建完全独立的新对象,与原对象内存隔离;Object.assign()等为浅拷贝;JSON.parse(JSON.stringify())最快但限制多;递归实现需WeakMap防循环引用;Lodash的cloneDeep()最稳妥。 深拷贝就是复制出一个完全独立的新对象 JavaScript 中的
Object.assign()
、展开运算符
{...obj}
或直接赋值
let b = a
都只是浅拷贝——它们只复制第一层属性,嵌套的对象或数组仍然共享引用。一旦修改嵌套内容,原对象也会被意外改变。深拷贝的目标是让新对象和原对象在内存中彻底隔离,互不影响。 JSON.parse(JSON.stringify()) 最快但限制多 这是最常用的“取巧”方式,适合纯数据对象(只含字符串、数字、布尔、null、数组、普通对象),不支持
Date
、
RegExp
、
undefined
、
function
、
Symbol
、
BigInt
或循环引用。遇到这些会静默丢失或报错。
const obj = { a: 1, b: { c: 2 } }; const copy = JSON.parse(JSON.stringify(obj)); copy.b.c = 99; console.log(obj.b.c); // 2 —— 原对象未变
undefined
和函数会被忽略
Date
变成字符串(如
"2023-01-01T00:00:00.000Z"
) 循环引用直接抛
TypeError: Converting circular structure to JSON
递归实现能处理函数和 Date,但要小心循环引用 手写深拷贝的核心是:遍历每个属性,对对象/数组递归调用自身,对基本类型直接返回。关键难点在于检测并缓存已访问过的对象,避免无限递归。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载
function deepClone(obj, map = new WeakMap()) { if (obj === null || typeof obj !== 'object') return obj; if (map.has(obj)) return map.get(obj); const cloned = Array.isArray(obj) ? [] : {}; map.set(obj, cloned); for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { cloned[key] = deepClone(obj[key], map); } } return cloned; }
用
WeakMap
缓存源对象 → 克隆对象映射,解决循环引用 保留
Date
、
RegExp
、
Map
、
Set
等类型需额外判断分支 无法克隆
function
的 作用域 或闭包,但函数本身可被复制(因函数是对象,且通常不需要“深”进函数体) Lodash 的
cloneDeep()
是生产环境最稳妥的选择 它覆盖了几乎所有边界情况:
Map
、
Set
、
TypedArray
、
Buffer
、
Error
、循环引用、不可枚举属性、原型链等。体积稍大,但省去自己踩坑的成本。 立即学习 “ Java免费学习笔记(深入) ”;
import { cloneDeep } from 'lodash-es'; const obj = { date: new Date(), map: new Map([['a', 1]]) }; const copy = cloneDeep(obj); console.log(copy.date instanceof Date); // true console.log(copy.map.size); // 1
不依赖全局
JSON
,兼容性更好 对
undefined
、
Symbol
、
BigInt
也能保留(取决于版本) 如果项目已用 Lodash,直接用;否则引入单个函数比手写更可靠 实际项目里,别硬刚“最简实现”。循环引用、稀疏数组、带 getter 的对象、Proxy 实例……这些细节加起来,会让手写深拷贝迅速变得不可维护。真正需要深拷贝的地方,往往也意味着数据结构已经复杂到值得依赖成熟方案。

相关文章