深拷贝(deepClone)浅拷贝(shallowCopy)

先看一个例子:函数

// 对象类型在赋值的过程当中实际上是复制了地址,从而会致使改变了一方其余也都被改变的状况
let a = {
  age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2
复制代码

浅拷贝

首先能够经过 Object.assign 来解决这个问题,不少人认为这个函数是用来深拷贝的。其实并非,Object.assign 只会拷贝全部的属性值到新的对象中,若是属性值是对象的话,拷贝的是地址,因此并非深拷贝。ui

let a = {
  age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
复制代码

另外咱们还能够经过展开运算符 ... 来实现浅拷贝spa

let a = {
  age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1
复制代码

一般浅拷贝就能解决大部分问题了,可是当咱们遇到以下状况就可能须要使用到深拷贝了code

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
  • 不能序列化函数
  • 不能解决循环引用的对象

在遇到函数、 undefined 或者 symbol 的时候,该对象也不能正常的序列化原型

let a = {
  age: undefined,
  sex: Symbol('male'),
  jobs: function() {},
  name: 'yck'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "yck"}
复制代码

你会发如今上述状况中,该方法会忽略掉函数和 undefined,可是在一般状况下,复杂数据都是能够序列化的,因此这个函数能够解决大部分问题。string

若是你所需拷贝的对象含有内置类型而且不包含函数,最好的方式是推荐[lodash 的深拷贝函数],由于实现一个深拷贝是很困难的,须要考虑好多种边界状况,好比原型链如何处理、DOM 如何处理等等it

在此实现一个简易版的深拷贝

// 递归拷贝
function deepClone(obj) {
  let copy = obj instanceof Array ? [] : {}
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
    }
  }
  return copy
}
复制代码
相关文章
相关标签/搜索