JavaScript 实现深拷贝

JavaScript 的 deepClone(深拷贝)需要处理 基本类型、引用类型(对象、数组)、特殊对象(日期、正则、函数) 等场景,还要避免 循环引用 导致的死循环

  1. 支持基本类型 :数字、字符串、布尔值、nullundefinedSymbolBigInt(直接返回原值,无拷贝成本)。
  2. 支持引用类型
    • 普通对象({})、数组([]
    • 特殊对象:Date(拷贝时间戳)、RegExp(拷贝源正则和修饰符)
  3. 解决循环引用 :用 WeakMap 缓存已拷贝的对象,避免循环引用导致的栈溢出(例如 a.b = a 场景)。
  4. 保留属性特性 :通过 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
}
相关推荐
木斯佳4 小时前
前端八股文面经大全:bilibili生态技术方向二面 (2026-03-25)·面经深度解析
前端·ai·ssd·sse·rag
不会写DN4 小时前
Gin 日志体系详解
前端·javascript·gin
冬夜戏雪5 小时前
实习面经记录(十)
java·前端·javascript
爱学习的程序媛6 小时前
【Web前端】JavaScript设计模式全解析
前端·javascript·设计模式·web
小码哥_常6 小时前
从SharedPreferences到DataStore:Android存储进化之路
前端
老黑6 小时前
开源工具 AIDA:给 AI 辅助开发加一个数据采集层,让 AI 从错误中自动学习(Glama 3A 认证)
前端·react.js·ai·nodejs·cursor·vibe coding·claude code
薛先生_0997 小时前
js学习语法第一天
开发语言·javascript·学习
jessecyj7 小时前
Spring boot整合quartz方法
java·前端·spring boot
苦瓜小生7 小时前
【前端】|【js手撕】经典高频面试题:手写实现function.call、apply、bind
java·前端·javascript
天若有情6737 小时前
前端HTML精讲03:页面性能优化+懒加载,搞定首屏加速
前端·性能优化·html