具有深度克隆的Object.assign()方法

时间:2019-07-14 13:49:48

标签: javascript

我在理解为什么使用assign()方法时源对象内部的嵌套对象没有被复制到目标对象中时遇到了麻烦,

const original = {
  name: 'Fiesta',
  car: {
    color: 'blue'
  }
}
const copied = Object.assign({}, original)

original.name = 'Lamborghini'
original.car.color = 'red'

console.log(original); // color: "red", name: "Lamborghini"
console.log(copied); //   color: "red", name: "Fiesta"

我原本希望copy.name是“ Lamborghini”,因为后来它被更改为“ Lamborghini”,有人可以解释为什么吗?

2 个答案:

答案 0 :(得分:0)

自从您更新了问题之后:现在我想您根本不希望使用Object.assign。您似乎想要的是因为您甚至希望在更新“ copy”时更改“ original”的名称,是将副本设置为与原始引用相同的对象的引用/指针< / p>

您可以简单地:将const copy = original设置为获得该结果。

const original = {
name: 'porsche',
car: { color: 'green' }
}
const copied = original
original.name = 'Lamborghini'
document.write(copied.name)
// despite copied being a "copy" of original... it gets all the updates that original gets.

// That's because copy is not a copy at all but rather a pointer just like original is a pointer and they both point to the same object in the heap of memory.

您可以在内存/对象中具有指向同一空间的多个指针,这将允许您修改指针的键之一,然后将其更改为所有指针。这是给参考的分配。


这与为什么Object.assign不是深度克隆的原因有关: 这是因为对象仅包含对嵌套对象指针的引用。

具体地说,

对象:

{
    color: 'blue'
}

是您没有将Object.assign应用于...的对象,因此具有:color: "0xC32332"

“ 0xC32332”是指向内存空间的指针,该空间包含具有键颜色和当前值blue的对象。

执行Object.assign时,您没有更改值-从键car(又称对象)开始,您只是在创建指向内存中相同对象/空间的新指针。

因此,如果要使用Object.assign()进行“深层”克隆 您必须递归调用它。

const recursiveDeep = (obj) => {
  return Object.keys(obj).reduce((newObj, currentKey) => {
    if (typeof obj[currentKey] === 'object'){
      newObj[currentKey] = recursiveDeep(obj[currentKey])
    }
    else {
      newObj[currentKey] = obj[currentKey]
    }
    return newObj
  }, {})
}

const original = {
  name: 'porsche',
  car: { color: 'green' }
}
const copied = recursiveDeep(original)

original.name = 'Lamborghini'
original.car.color = 'red'
document.write(copied.name)
document.write(copied.car.color)

答案 1 :(得分:0)

copiedoriginal的浅表克隆,因此将克隆所有顶级属性。在原件上更改其中之一(例如名称),不会在克隆上更改(这就是克隆的重点)。

嵌套在原始对象中的汽车对象不会被克隆,因此更改其中的属性仍然会导致originalcopied都发生更改。