JavaScript 的
deepClone(深拷贝)需要处理 基本类型、引用类型(对象、数组)、特殊对象(日期、正则、函数) 等场景,还要避免 循环引用 导致的死循环
- 支持基本类型 :数字、字符串、布尔值、
null、undefined、Symbol、BigInt(直接返回原值,无拷贝成本)。 - 支持引用类型 :
- 普通对象(
{})、数组([]) - 特殊对象:
Date(拷贝时间戳)、RegExp(拷贝源正则和修饰符)
- 普通对象(
- 解决循环引用 :用
WeakMap缓存已拷贝的对象,避免循环引用导致的栈溢出(例如a.b = a场景)。 - 保留属性特性 :通过
Reflect.ownKeys遍历所有可枚举 / 不可枚举属性,包括Symbol类型的键(比for...in更全面)。
JavaScript
function deepClone(target, hash = new WeakMap()) {
// 1. 处理基本类型和 null/undefined(直接返回,无需拷贝)
if (target === null || typeof target !== "object") return target
// 2. 处理循环引用(已拷贝过的对象直接返回缓存)
if (hash.has(target)) return hash.get(target)
let cloneObj
// 3. 处理日期对象
if (target instanceof Date) {
cloneObj = new Date(target)
hash.set(target, cloneObj)
return cloneObj
}
// 4. 处理正则对象
if (target instanceof RegExp) {
cloneObj = new RegExp(target.source, target.flags)
hash.set(target, cloneObj)
return cloneObj
}
// 5. 处理 Map
if (target instanceof Map) {
cloneObj = new Map()
hash.set(target, cloneObj)
target.forEach((value, key) => {
cloneObj.set(deepClone(key, hash), deepClone(value, hash))
})
return cloneObj
}
// 6. 处理 Set
if (target instanceof Set) {
cloneObj = new Set()
hash.set(target, cloneObj)
target.forEach((value) => {
cloneObj.add(deepClone(value, hash))
})
return cloneObj
}
// 7. 处理数组和普通对象(区分数组和对象的构造器)
cloneObj = Array.isArray(target) ? [] : {}
hash.set(target, cloneObj)
// 8. 遍历对象/数组的可枚举属性(包括 Symbol 类型)
Reflect.ownKeys(target).forEach((key) => {
// 递归拷贝属性值,同时传递 hash 缓存
cloneObj[key] = deepClone(target[key], hash)
})
return cloneObj
}