Skip to content

深拷贝 ​

js
function deepClone(obj, map = new WeakMap()) {
  // null 或非对象 → 直接返回
  if (typeof obj !== 'object' || obj === null) return obj

  // 循环引用:已经拷贝过 → 返回之前的结果
  if (map.has(obj)) return map.get(obj)

  const clone = Array.isArray(obj) ? [] : {}
  map.set(obj, clone)

  // 拷贝可枚举属性
  for (const key of Object.keys(obj)) {
    clone[key] = deepClone(obj[key], map)
  }

  // 拷贝 Symbol 属性
  for (const sym of Object.getOwnPropertySymbols(obj)) {
    clone[sym] = deepClone(obj[sym], map)
  }

  return clone
}

面试要点:

  • 基本类型直接返回
  • 数组/对象递归拷贝
  • WeakMap 处理循环引用(a.b = a)
  • Symbol key 也要拷贝(Object.getOwnPropertySymbols)
  • 不需要处理 Date/RegExp/Map/Set 等特殊类型(除非面试官要求)

循环引用问题 ​

js
const obj = { name: 'a' }
obj.self = obj  // 自引用

// 没有 WeakMap → 无限递归 → 栈溢出
// 有 WeakMap → map.has(obj) → true → 直接返回

基于 Vue 2.7 & Vue 3.4 源码