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
}
相关推荐
90后的晨仔7 小时前
从 H5 到 uni-app:一篇写给前端小白的"翻译指南"
前端·vue.js·前端框架
陈随易8 小时前
moon,apt和yum之外linux系统命令安装新选择
前端·后端·程序员
IT小盘8 小时前
13-企业Prompt模板-角色任务约束与输出格式
java·前端·prompt
徐小夕9 小时前
开源!我用SQLite + DuckDB打造了一款可视化AI问数平台
前端·算法·github
leslie1189 小时前
babel笔记
前端
用户0595401744610 小时前
Redis 记忆存储踩坑实录:一个并发写入 Bug 让我排查了 4 小时
前端·css
小徐_233310 小时前
Wot UI 2.3.0 发布:二维码组件来了,Open Wot 与 wot-starter 同步更新
前端·微信小程序·uni-app
kyriewen11 小时前
Claude自己跑出去hack了3家公司——我为什么还在用它写代码
前端·ai编程·claude
IT_陈寒11 小时前
SpringBoot自动配置的坑,这次真踩疼我了
前端·人工智能·后端
子兮曰11 小时前
AI 浏览器 Agent 的安全困局:当自动化工具可以偷走你的登录态
前端·人工智能·后端