Skip to content

深浅拷贝

js
let a = {
  age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2

从上,若给一变量赋值一对象,两者值会是同一个引用,其一修改另一也会改变。

浅拷贝

首先可通过Object.assign来解决

js
let a = {
  age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1

还可以通过展开运算符来解决

js
let a = {
  age: 1
}
let b = {...a}
a.age = 2
console.log(b.age) // 1

通常浅拷贝就能解决大部分问题了,但是当我们遇到如下情况需要深拷贝:

js
let a = {
  age: 1,
  jobs: {
    first: 'FE'
  }
}
let b = {...a}
a.jobs.first = 'VUE'
console.log(b.jobs.first)

浅拷贝只解决第一层的问题,如果接下去的值中还有对象,那么又回到之前的问题,两者共享引用,解决这个问题就引入了深拷贝

深拷贝

一般地,可以通过 JSON.parse(JSON.stringify(obj))来解决

但该方法有局限性:

  • 会忽略 undefined
  • 不能序列化函数
  • 不能解决循环引用的对象

如果你所需拷贝的对象含有内置类型并且不包含函数,可以使用 MessageChannel

js
function deepClone(obj) {
  return new Promise(resolve => {
    const {port1, port2} = new MessageChannel()
    port2.onmessage = ev => resolve(ev.data)
    port1.postMessage(obj)
  })
}
var obj = {
  a: 1,
  b: {
    c: b
  }
}
// 注意,该方法是异步的,可以处理undefined和循环引用对象
const clone = await deepClone(obj)

共 20 个模块,1301 篇 Markdown 文档。