2017-06-20 62 views
2

我刚刚注意到克隆和推送项目有点奇怪。这里的例子: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 

现在我对对象做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]

问题是:为什么?

+0

原因'a.foo'是'[1,2,3,4]'和'b.foo'是'[1,2,3]'是'concat()'返回一个全新的数组这将取代'a.foo' – Miqe

回答

2

Object.assign做一些事情,被称为shallow cloningshallow copying 。如果源值是对对象的引用,则它只复制该引用值。

检查docs here并阅读深层克隆警告

这也是为什么一个push影响两个对象ab,因为它实际上是在其上操作发生的相同阵列。

Array.prototype.concat方法返回一个新 Array对象,它分配给a.foo(a.foo = a.foo.concat(4)),所以二者foo的引用现在将指向2个不同的阵列对象。

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

                                                              Object references

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)

+0

你为什么要做foo.bar === baz.bar,解释为什么foo ===巴兹是假的,如果它是一个黄色的副本 – AurA

+0

@AurA为什么会这样? –

+0

这将是错误的,因为它是一个对象和对象结构被复制到浅拷贝中,但变量指向相同,这就是它在这里返回false的原因...它是一个空对象,但结构仍然被复制... – AurA

3

a.foo和b.foo都指向相同的参考,但是,这样他们现在指向.concat()返回一个新的阵列2不同阵列基准

0

读到这里

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

分配不这样做的深层副本,所以a.foo和b.foo指向同一个数组,所以当你把它被添加到同一阵列

但是当你做concat它实际上返回新阵列,现在两个阵列不同

+0

那么为什么一个=== b给出错误? – AurA

+0

假设它像这样 一个= {X:Y} 现在 B = {} 然后b.x = a.x 你应该看到,显然是不同的,但关键有相同的价值观.. –

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()将只是参考复制等植物学对象。