深浅拷贝

39 阅读2分钟

1.浅拷贝

如果要拷贝的属性为简单数据类型,则拷贝值,引用数据类型拷贝地址,简单来说就是只拷贝一层

实现浅拷贝的方式:

  • Object.assign(target,source)//把源对象拷贝到目标对象上
  • slice()
  • concat()
  • {...}

写一个简单的吧

const shallowCopy = function(oldObj){
    const newObj = {}
    for(let i of oldObj){
        //用hasOwnProperty来判断是否是自有属性
        if(oldObj.hasOwnProperty(i)){
            newObj[i] = oldObj[i]
        }
    }
    return newObj
}

2.深拷贝

深拷贝会开辟一个新的栈,拷贝的对象属性与原来完全相同,但是由于对应着不同的地址,一个的更改不会影响到另一个

实现深拷贝的方法

  • JSON.stringify()
  • 各种库的方法,如lodash的_.cloneDeep

再写一个深拷贝吧

const copy = function (oldObj, hash = new WeakMap()) {
  //1.处理特殊类型
  if (oldObj === null) return oldObj;
  if (oldObj instanceof Date) return new Date(oldObj);
  if (oldObj instanceof RegExp) return new RegExp(oldObj);
  //2.处理数组和对象
  if (typeof oldObj !== "object") return oldObj;
  let newObj = Array.isArray(oldObj) ? [] : {};
  //为了防止循环引用,我们可以额外开辟一个存储空间,,来存储当前对象和拷贝对象间的关系,
  //当准备拷贝对象时,如果这个对象已经存储在map中了,如果拷贝过了就直接返回,没有就加入
  if (hash.get(oldObj)) {
    return hash.get(oldObj);
  }
  hash.set(oldObj, newObj);
  //3.递归遍历对象
  for (let i in oldObj) {
    if (oldObj.hasOwnProperty(i)) {
      newObj[i] = copy(oldObj[i], hash);
    }
  }
  return newObj;
};

这里解释下为什么用WeakMap类型:

如果用map的话他是强引用类型这意味着只要 Map 对象存在,所有的键都会存在,不会被垃圾回收器回收。 WeakMap:对于键对象是弱引用,这意味着如果键对象没有被其他部分的代码所引用,它可能会被垃圾回收器回收,从而使得相应的键值对从 WeakMap 中删除。这样对内存更加友好