Javascript数组推送更新也克隆了对象

时间:2017-06-20 08:00:16

标签: javascript

我刚注意到克隆和推送物品的奇怪之处。这是一个例子:

let a = { foo: [1,2] };
let b = Object.assign({}, a) // cloning object and getting new reference
a === b // gives false which is what I want

现在我在对象a上做push

a.foo.push(3)

现在a.foo[1,2,3]b.foo也是[1,2,3]

但如果我这样做

a.foo = a.foo.concat(4)

a.foo[1,2,3,4]b.foo[1,2,3]

问题是:为什么?

5 个答案:

答案 0 :(得分:3)

a.foo和b.foo指向相同的引用,但.concat()返回一个新数组,因此它们现在指向2个不同的数组引用

答案 1 :(得分:2)

Object.assign执行的操作称为shallow cloningshallow copying。如果源值是对Object的引用,则它仅复制该引用值。

检查docs here并阅读 Deep Clone警告

这也是push影响对象ab的原因,因为它实际上是执行操作的相同数组。

Array.prototype.concat方法返回 new 数组对象,您将其指定给a.foo(a.foo = a.foo.concat(4)),因此两个foo引用现在将指向2个不同的数组对象

  

concat()方法用于合并两个或多个数组。这种方法   不会更改现有数组,而是返回一个新数组。

Object references

答案 2 :(得分:1)

  

为什么?

Object.assign({}, a)会对您的对象a

进行浅层复制

const foo = {bar: []}

const baz = Object.assign({}, foo)

console.log(foo.bar === baz.bar)

但是Array.prototype.concat会创建新数组

const foo = []
const bar = foo.concat()

console.log(foo === bar)

答案 3 :(得分:1)

因为在您的情况下a.foob.foo引用相同的数组。因此,一方的更改会影响另一方, Array.prototype.concat 会返回一个新数组并且不会改变第一个数组,这就是为什么在第二次调用中得到不同的结果,而不是到 array.prototype.push 这将改变初始数组。

<强> Array.prototype.concat

  

concat()方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

<强> array.prototype.push

  

push()方法将一个或多个元素添加到数组的末尾,并返回数组的新长度。

您可能还需要阅读What is the most efficient way to deep clone an object in JavaScript?,因为Object.assign()只会复制对现有对象的引用。

答案 4 :(得分:0)

在这里阅读

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

指定不做深度复制,所以a.foo和b.foo指向同一个数组,所以当你推送它时会被添加到同一个数组

但是当你做concat时它实际上返回了新数组,现在两个数组都是不同的