第60题 实现深拷贝

深拷贝和浅拷贝的区别就在于

  • 浅拷贝: 对于复杂数据类型,浅拷贝只是把引用地址赋值给了新的对象,改变这个新对象的值,原对象的值也会一起改变。
  • 深拷贝: 对于复杂数据类型,拷贝后地址引用都是新的,改变拷贝后新对象的值,不会影响原对象的值。

所以关键点就在于对复杂数据类型的处理,这里我写了两种写法,第二中比第一种有部分性能提升

    const isObj = (val) => typeof val === "object" && val !== null;
    
    // 写法1
    function deepClone(obj) {
        // 通过 instanceof 去判断你要拷贝的变量它是否是数组(如果不是数组则对象)。
    
        // 1. 准备你想返回的变量(新地址)。
        const newObj = obj instanceof Array ? [] : {}; // 核心代码。
    
        // 2. 做拷贝;简单数据类型只需要赋值,如果遇到复杂数据类型就再次进入进行深拷贝,直到所找到的数据为简单数据类型为止。
        for (const key in obj) {
            const item = obj[key];
            newObj[key] = isObj(item) ? deepClone(item) : item;
        }
    
        // 3. 返回拷贝的变量。
        return newObj;
    }
    // 写法2 利用es6新特性 WeakMap弱引用 性能更好 并且支持 Symbol
    function deepClone(obj, wMap = new WeakMap()) {
      if (isObj(obj)) {
        // 判断是对象还是数组
        let target = Array.isArray(obj) ? [] : {};
    
        // 如果存在这个就直接返回
        if (wMap.has(obj)) {
          return wMap.get(obj);
        }
    
        wMap.set(obj, target);
    
        // 遍历对象
        Reflect.ownKeys(obj).forEach((item) => {
          // 拿到数据后判断是复杂数据还是简单数据 如果是复杂数据类型就继续递归调用
          target[item] = isObj(obj[item]) ? deepClone(obj[item], wMap) : obj[item];
        });
    
        return target;
      } else {
        return obj;
      }
    }

这道题主要是的方案就是,递归加数据类型的判断

如是复杂数据类型,就递归的再次调用你这个拷贝方法 直到是简单数据类型后可以进行直接赋值

Last Updated:
Contributors: leeguooooo