深拷贝和浅拷贝的区别?如何实现深拷贝?
区别
- 浅拷贝:只复制第一层,嵌套的引用类型仍共享地址
- 深拷贝:递归复制所有层级,完全独立
const obj = { a: 1, b: { c: 2 } }
// 浅拷贝
const shallow = { ...obj }
shallow.b.c = 99
console.log(obj.b.c) // 99(共享引用)
// 深拷贝
const deep = structuredClone(obj)
deep.b.c = 99
console.log(obj.b.c) // 2(独立)浅拷贝方法
const copy1 = { ...obj } // 展开运算符
const copy2 = Object.assign({}, obj) // Object.assign
const arrCopy = [...arr] // 数组浅拷贝
const arrCopy2 = arr.slice() // 数组浅拷贝深拷贝方法
1. structuredClone(推荐,现代浏览器原生支持)
const clone = structuredClone(obj)
// 支持循环引用、Date、RegExp、Map、Set 等
// 不支持函数、Symbol、DOM 节点2. JSON 序列化(简单但有局限)
const clone = JSON.parse(JSON.stringify(obj))
// ❌ 不支持:undefined、function、Symbol、循环引用、Date→字符串、RegExp→空对象3. 手写深拷贝
function deepClone(obj, map = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj
if (obj instanceof Date) return new Date(obj)
if (obj instanceof RegExp) return new RegExp(obj)
if (obj instanceof Map) {
const clone = new Map()
map.set(obj, clone)
obj.forEach((v, k) => clone.set(deepClone(k, map), deepClone(v, map)))
return clone
}
if (obj instanceof Set) {
const clone = new Set()
map.set(obj, clone)
obj.forEach(v => clone.add(deepClone(v, map)))
return clone
}
// 处理循环引用
if (map.has(obj)) return map.get(obj)
const clone = Array.isArray(obj) ? [] : {}
map.set(obj, clone)
for (const key of Reflect.ownKeys(obj)) {
clone[key] = deepClone(obj[key], map)
}
return clone
}各方法对比
| 方法 | 循环引用 | 函数 | Date/RegExp | 性能 |
|---|---|---|---|---|
| structuredClone | ✅ | ❌ | ✅ | 好 |
| JSON.parse/stringify | ❌ | ❌ | ❌ | 中 |
| 手写 deepClone | ✅ | ✅ | ✅ | 可控 |