Skip to content

deepClone

深度克隆对象或数组,处理循环引用和各种数据类型。

函数签名

typescript
// 完整版深拷贝
function deepClone<T>(value: T, options?: DeepCloneOptions): T

interface DeepCloneOptions {
  includeNonEnumerable?: boolean
  includeSymbol?: boolean
  includePrototype?: boolean
  customClone?: (value: any, defaultClone: (v: any) => any) => any
}

// JSON 方式深拷贝
function deepCloneJSON<T>(value: T): T

// structuredClone 方式
function deepCloneStructured<T>(value: T, deps: DeepCloneStructuredDeps): T

interface DeepCloneStructuredDeps {
  structuredClone?: <T>(value: T) => T
}

参数

deepClone

参数名类型必填默认值说明
valueT-要克隆的值
optionsDeepCloneOptions{}克隆选项
options.includeNonEnumerablebooleanfalse是否克隆不可枚举属性
options.includeSymbolbooleanfalse是否克隆 Symbol 属性
options.includePrototypebooleanfalse是否保持原型链
options.customCloneFunction-自定义克隆函数

deepCloneJSON

参数名类型必填说明
valueT要克隆的值

deepCloneStructured

参数名类型必填说明
valueT要克隆的值
depsDeepCloneStructuredDeps依赖注入对象,包含 structuredClone 函数

前置依赖

deepCloneStructured

参数名类型说明
deps.structuredClone<T>(value: T) => TstructuredClone 函数(较新的浏览器原生 API)

环境要求

  • structuredClone: 原生深拷贝 API(Node.js 17+, 现代浏览器)
  • 如果环境不支持,会自动 fallback 到 deepClone
typescript
const deps = { 
  structuredClone: typeof structuredClone !== 'undefined' ? structuredClone : undefined 
}

返回值

类型说明
T克隆后的值

工作原理

deepClone (完整版)

  1. 处理基本类型:直接返回
  2. 检查循环引用:使用 WeakMap 记录已克隆对象
  3. 调用自定义克隆函数(如果提供)
  4. 处理特殊对象类型:
    • Date: 创建新 Date 实例
    • RegExp: 复制 source 和 flags
    • Error: 复制 message、stack、name
    • Map/Set: 递归克隆键和值
    • WeakMap/WeakSet: 创建新实例
    • ArrayBuffer: 复制二进制数据
    • TypedArray/DataView: 创建新实例并复制数据
  5. 处理数组:递归克隆每个元素
  6. 处理普通对象:
    • 根据选项决定是否保持原型链
    • 递归克隆可枚举属性
    • 根据选项决定是否克隆不可枚举属性和 Symbol 属性

deepCloneJSON (简易版)

  1. 使用 JSON.stringify 将对象序列化为字符串
  2. 使用 JSON.parse 将字符串反序列化为新对象
  3. 缺点:无法处理函数、undefined、Symbol、循环引用、Date、RegExp 等
  4. 注意JSON 是 JavaScript 标准内置对象,所有环境均可用

deepCloneStructured (原生 API)

  1. 如果提供了 deps.structuredClone:使用原生 API
  2. 否则:Fallback 到 deepClone
  3. 优点:性能最好,支持更多类型(Blob、File)
  4. 缺点:不支持函数和 Symbol
  5. 需要依赖注入:因为是较新的 API,旧环境不支持

适用于需要完全隔离原对象和克隆对象的场景。