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
}
相关推荐
朦胧之16 小时前
AI 编程-老项目改造篇
java·前端·后端
swipe18 小时前
从 0 到 1 实现大文件上传:分片、秒传、断点续传、暂停、重试与服务端合并
前端·javascript·面试
爱勇宝18 小时前
我做了一个只用来搜歌词的小 App
android·前端·后端
甲维斯19 小时前
用AI还原《坦克大战》并3D化升级!
前端·人工智能·游戏开发
IT_陈寒19 小时前
SpringBoot自动配置坑了我一晚上,原来问题出在这
前端·人工智能·后端
kyriewen20 小时前
AI 生成的代码能跑就行?这 5 个坑迟早炸
前端·javascript·ai编程
kisshyshy20 小时前
🍦 雪糕、食堂、火车厢:三幅漫画吃透栈、队列与链表
javascript·算法
谷子在生长20 小时前
纯血鸿蒙自定义弹窗最佳实践:从「到处复制」到「一行调用」
前端·harmonyos
壹方秘境20 小时前
我用Go语言开发了一个跨平台的HTTPS抓包和调试工具
前端·后端·ios
神秘面具男20 小时前
HarmonyOS 6.0跨端远程控制
前端·后端