深拷贝(手写递归-weakMap)

343 阅读1分钟

1、定义一个判断是否为对象的函数

function isObj(val) {
  return typeof val === "object" && val !== null;
}

2、定义deepClone函数,传入obj和一个Hash值,用来记录已经克隆过的对象,避免无线递归

 function deepClone(obj, hash = new weakMap()) {}

3、如果对象已经存在Hash表,则直接返回Hash表中该对象的克隆副本,避免重复克隆

if (hash.has(obj)) {
  return hash.get(obj)
}

4、根据对象的类型创建一个target,如果是数组则创建一个空数组,否则创建一个空对象

 const target = Array.isArray(obj) ? [] : {}

5、将对象与目标对象存入哈希表中,建立对象到目标对象的映射关系

 hash.set(obj, target)

6、遍历对象中所有的可枚举属性,包括自有属性和继承属性,使用Reflect.ownKeys方法获取属性列表。对于每个属性,判断是否为对象类型,如果是对象则递归调用deepClone函数进行深度克隆,否则直接将值复制到目标对象上。

 Reflect.ownKeys(obj).forEach(item => {
    if (isObj(obj[item])) {
      target[item] = deepClone(obj[item], hash)
    } else {
      target[item] = obj[item]
    }
  })
  return target

完整函数

function isObj(val) {
      return typeof val === 'object' && val !== null
}
function deepClone(obj, hash = new weakMap()) {
  if (!isObj(obj)) return obj
  if (hash.has(obj)) {
    return hash.get(obj)
  }
  const target = Array.isArray(obj) ? [] : {}
  hash.set(obj, target)
  Reflect.ownKeys(obj).forEach(item => {
    if (isObj(obj[item])) {
      target[item] = deepClone(obj[item], hash)
    } else {
      target[item] = obj[item]
    }
  })
  return target
}

# const obj1 = {
#   a: 1,
#   b: { a: 2 }
# };
# const obj2 = deepClone(obj1);
# console.log(obj1);