JS--浅拷贝和深拷贝

599 阅读1分钟

1. 浅拷贝,基本类型复制值,引用类型复制引用,若源数据或拷贝后的数据的引用类型的值发生变化,则另一方随之改变。

// 浅拷贝

function clone(target) {
  let cloneTarget = {}
  for (let key in target) {
    cloneTarget[key] = target[key]
  }
  return cloneTarget
}

// test
let obj = {a: 1}

let obj2 = {b: obj}

let cloneObj2 = clone(obj2)

cloneObj2.b.a = 2

console.log(obj)    // {a: 2}

2. 深拷贝,如果是基本类型则直接返回,如果是引用类型就创建一个新对象,遍历需要克隆的对象,将需要克隆的对象的属性执行深拷贝后依次添加到新对象上。考虑到循环引用问题,需要创建一块内存空间来存储已经克隆过的对象,在克隆对象之前先去这块空间里找一下有没有克隆过,有的话就返回,没有的话就把当前对象作为 key, 克隆对象作为 value 进行存储,再继续克隆。

//深拷贝

function clone(target, map = new WeakMap()) {
  if (typeof target === 'object' || typeof target === 'function' && target !== null) {
    let cloneTarget = Array.isArray(target) ? [] : {}

    if (map.get(target)) {
      return map.get(target)
    }

    map.set(target, cloneTarget)

    for (let key in target) {
      cloneTarget[key] = clone(target[key], map)
    }

    return cloneTarget
  } else {
    return target
  }
}

当然,大部分情况下都可以使用序列化对象的方式,但这种方式不能正确处理函数、正则、循环引用等情况

JSON.parse(JSON.stringify(target))