js 深拷贝

71 阅读1分钟
function cloneDeep(obj, map = new WeakMap()) {
  // 判断传入的参数是否为对象,如果为空,返回原值
  if (typeof obj !== 'object' || !obj) return obj
  // 避免循环引用
  const objFromMap = map.get(obj)
  // 如果已经存在,则直接返回
  if (objFromMap) return objFromMap
  let target: any = {}
  map.set(obj, target)

  // Map
  if (obj instanceof Map) {
    target = new Map()
    obj.forEach((v, k) => {
      const v1 = cloneDeep(v, map)
      const k1 = cloneDeep(k, map)
      target.set(k1, v1)
    })
  }

  // Set
  if (obj instanceof Set) {
    target = new Set()
    obj.forEach((v) => {
      const v1 = cloneDeep(v, map)
      target.add(v1)
    })
  }

  // Array
  if (obj instanceof Array) {
    target = obj.map((item) => cloneDeep(item, map))
  }

  // Date
  if (obj instanceof Date) {
    // 返回一个新的Date对象
    target = new Date(obj)
  }

  // Function
  if (obj instanceof Function) {
    target = obj
  }

  // Object
  for (const key in obj) {
    const val = obj[key]
    target[key] = cloneDeep(val, map)
  }
  return target
}