阅读 50

深copy原理

一、数组(基本数据类型)&单层对象

 第一步:对于深copy它只适用于数组或者对象,它们的数据类型都是object;要排除其它特殊的数据类型:null,undefined,number,new Date()...

 第二步:区分是对象还是数组,深copy的本质就是原本是何种类型,在copy之后就返回何种类型。
 仅仅通过两步就可实现对象的简单的深copy,接下来就开始深入咯!

二、多层对象

 第一步:多层对象原本的copy是浅copy。如果实现深copy的话,证明里面还是个对象,需要递归实现深copy。


 第二步:多层对象应用封装好的函数deepClone实现深copy

 第三步:深copy成环问题引起的爆栈问题解决
  小例子:promise中的循环引用(死循环),深copy这里也出现成环问题

        let obj = {}
        obj.b = obj
        console.log(obj)//{ b: [Circular] }
复制代码

  成环问题解决:

  // 使用WeakMap结构存储已经拷贝的对象,每次进行拷贝时,
  // 就先向WeakMap查询该对象是否被拷贝,如果已拷贝就去除该对象并返回
  function deepClone(obj,hash=new WeakMap()) {
     if (obj == null) return obj
     if (typeof obj != "object") return obj
     if (obj instanceof Date) return new Date(obj)
     //WeakMap中存着已经copy的对象,判断WeakMap中有没有数据,如果有直接返回
     if(hash.has(obj)){
        return hash.get(obj)//返回获取到的数据
     }
     let newObj = new obj.constructor
     // 给新生产的对象设置数据,其键按照weakMap必须是对象
     hash.set(obj,newObj)//制作出映射表
     for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            // deepClone现在存在两个参数,一个数据,一个weakmap
            newObj[key] = deepClone(obj[key],hash)
        }
     }
    return newObj
}

  // 成环,陷入死循环
  let obj = {}
  obj.b = obj
  let a = {name:"tanni",age:obj}
  console.log(deepClone(a))

复制代码