深拷贝 浅拷贝

浅拷贝
⾸先可以通过 Object.assign 来解决这个问题,很多⼈认为这个函数是⽤来 深拷⻉的。其实并不是, Object.assign 只会拷⻉所有的属性值到新的对象中,如果属性值是对象的话,拷⻉的是地址,所以并不是深拷⻉。
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
另外我们还可以通过展开运算符 ... 来实现浅拷⻉
let a = {
age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1

通常浅拷⻉就能解决⼤部分问题了,但是当我们遇到如下情况就可能需要使⽤ 到深拷⻉了--
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = { ...a }
a.jobs.first = 'native'
console.log(b.jobs.first) // native
浅拷⻉只解决了第⼀层的问题,如果接下去的值中还有对象的话,那么就⼜回 到最开始的话题了,两者享有相同的地址。要解决这个问题,我们就得使⽤深拷⻉了。

深拷贝
这个问题通常可以通过 JSON.parse(JSON.stringify(object)) 来解决。
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE

但是该⽅法也是有局限性的:
·会忽略 undefined
·会忽略 symbol
·不能序列化函数
·不能解决循环引⽤的对象

  let obj = {
       a: 1,
       b: {
          c: 2,
          d: 3,
       },
  }
  obj.c = obj.b
  obj.e = obj.a
  obj.b.c = obj.c
  obj.b.d = obj.b
  obj.b.e = obj.b.c
  let newObj = JSON.parse(JSON.stringify(obj))
  console.log(newObj)

简单来说深拷贝就是当遇到值是对象类型的时候就再运行一遍复制:

  function deepCopy (obj) {
      var result;
      //引用类型分数组和对象分别递归
      if (Object.prototype.toString.call(obj) == '[object Array]') {
        result = []
        for (i = 0; i < obj.length; i++) {
          result[i] = deepCopy(obj[i])
        }
      } else if (Object.prototype.toString.call(obj) == '[object Object]') {
        result = {}
        for (var attr in obj) {
          result[attr] = deepCopy(obj[attr])
        }
      }
      //值类型直接返回
      else {
        return obj
      }
      return result
  }
posted @ 2021-12-30 15:35  ·灯  阅读(37)  评论(0编辑  收藏  举报