【查漏补缺】深浅拷贝

86 阅读2分钟

前言

之前对深浅拷贝没有很多认识,一开始对深浅拷贝仅仅只是通过面试题或者一些掘金文章来认识的,所以在一段时间提起深浅拷贝仍旧是一个模糊的看法。其实深浅拷贝应用的范围很关,如果对于深浅拷贝没有一个很好的认识,在一些方面会很容易写出bug。

一开始在看深浅拷贝,仅仅记住就是浅拷贝是对于基本数据类型是不会影响到源对象,而引用类型就是拷贝的其地址值。而深拷贝就是完全拷贝源对象的键值对,修改一方不会修改到源对象。

浅拷贝原理

其实,浅拷贝如果仅仅认识到是对两种数据类型的处理,那么对于区分深拷贝是会迷惑的,在一些API上面会区分不了这是浅拷贝还是深拷贝,我就对Object.assign是浅拷贝还是深拷贝迷惑了,其实浅拷贝很简单,就是按照字面意思理解,它是很简单的对对象进行拷贝,只完全拷贝了对象的一层属性值,但是这一层属性值是引用类型,那么就是拷贝的是其地址值。

这有很多运用到浅拷贝的API,如Object.assign,扩展运算...等。

手写浅拷贝

function shallowCopy (target) {
    let result = Array.isArray(target) ? [] : {}
    //遍历target
    for (var key in target) {
      //排除原型上的属性干扰
      if (target.hasOwnProperty(key)) {
        result[key] = target[key]
      }
    }
    return result
}

深拷贝原理

深拷贝就是完全拷贝源对象,一层层遍历源对象的键值对,然后将其赋值到一个新的对象里,修改当前对象不会影响到源对象,因为当前对象和源对象不是保存同个地址值。

有一些方式可以实现深拷贝,如JSON.stringfy(只能拷贝对象的属性不能拷贝对象的方法和一些特殊值)、还有lodash也可以。

手写深拷贝

function deepClone(target, result) {
  let result = result || {}
  //遍历target
  for (let key in target) {
    //排除原型属性干扰
    if (target.hasOwnProperty(key)) {
      //引用类型就迭代
      if (targer[key] !== null && typeof target[key] === 'object') {
        result = Array.isArray(target[key])? [] : {}
        deepClone(target[key], result[key])
      } else {
        //基本数据类型就直接复制
        result[key] = target[key]
      }
    }
  } 
}