原生js实现对象的深拷贝

我们使用Object.assign(target,…sources)时,其实只是浅拷贝。只能复制第一层属性,而如果第一层属性中有对象或数组的话,其实只是对对象或数组的引用而已。
我们修改target里的对象属性时,source对象中对应的对象属性也会改变

    let source = {
    
    
      age: 'nice',
      obj: {
    
    
        name: 'nice'
      }
    }
    let target = {
    
    }
    Object.assign(target, source)
    target.obj.name = 'change'
    console.log(target.obj.name)   //change
    console.log(source.obj.name)   //change

要想实现深拷贝:

    function deepCopy(target, source) {
    
    
      if (source == null) {
    
    
        return
      }
      for (let i in source) {
    
    
        if (Object.prototype.hasOwnProperty.call(source, i)) {
    
    
          console.log(i)
          console.log(typeof i)
          if (typeof source[i] == 'object') {
    
    
            target[i] = {
    
    }
            deepCopy(target[i], source[i])
          } else {
    
    
            target[i] = source[i]
          }
        }
      }
    }

需要注意的是 for …in 循环中读取出来的变量都转换成string了,所以在递归传参一定要注意用
deepCopy(target[i], source[i])

2020.9.6记
上面的深拷贝仅仅实现了对象的深拷贝,没有考虑到数组的情况。下面代码兼具了数组和对象:

function deepCopy(target) {
    
    
  let result;
  if (Object.prototype.toString.call(target) === "[object Array]") {
    
    
    result = [];
    target.forEach((element) => {
    
    
      result.push(deepCopy(element));
    });
  } else if (Object.prototype.toString.call(target) === "[object Object]") {
    
    
    result = {
    
    };
    Object.keys(target).forEach((key) => {
    
    
      result[key] = deepCopy(target[key]);
    });
  } else {
    
    
    result = target;
  }
  return result;
}

顺便总结一下js判断数据类型的几种方式和优缺点。

Object.prototype.toString.call()   //这个方法是最好了,可以明确的区分各种类型
typeof            //这个区分不出来数组和对象和null。
Array.isArray()   //这个用来区分数组
instanceof   //无法区分null 和 undefined

猜你喜欢

转载自blog.csdn.net/qq_42535651/article/details/104378693
今日推荐