2017-06-20 33 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()將只是參考複製等植物學對象。