2011-07-06 45 views
7

我有以下代碼(我用的是jQquery libary):有人可以解釋我這個JavaScript對象「複製」行爲

var obj = {}; 
var objstring = '{"one":"one","two":"two","three":"three"}' 

// first console output 
console.log(objstring); 

var jsonobj = $.parseJSON(objstring); 

// second console output 
console.log(jsonobj); 

obj.key = jsonobj; 
obj.key.test = "why does this affect jsonobj? (even in the second console output)"; 

// third console output 
console.log(jsonobj); 

我的問題: 當我做obj.key = jsonobj我改​​變新的obj.key中的值。爲什麼jsonobj中的值也會改變?我將如何避免這種情況? (我想要一個新的jsonobj「副本」)。

我做了這個測試案例:http://jsfiddle.net/WSgVz/

+5

出色的問題和測試用例。現在這種情況非常罕見,令人難以置信的令人難過。 –

回答

3

這是因爲對象是不可複製的。 obj.key屬性將僅包含對該對象的引用,因此,當您將某些內容分配給obj.key.test時,其效果與分配給jsonobj.test的效果相同。

您可以使用jQuery的方法extend創建一個副本:

obj.key = $.extend({}, jsonobj); 

這將值複製到新創建的對象({})。

+3

同樣值得注意的是你需要'.extend(true,{},jsonobj)'來進行深層複製(而不是淺一層複製)。 – Domenic

+0

@Domenic:好的一點,對於更復雜的對象結構來說,這很好。 – Guffa

2

因爲當你做obj.key = jsonobj,沒有在obj.key一些新的,複製的對象;它只是對已經存在的jsonobj的引用。所以對obj.key的更改也將更改爲jsonobj,因爲它們實際上是同一件事。

1

這是因爲有沒有複製正在進行 - 只有一個對象,它是由referenced各種變量和屬性。當你做obj.key = jsonobj時,你只是將引用複製到同一個對象。

1

在JavaScript中的所有對象都通過引用複製,這意味着:

var x = {}; 
var y = x; 
x.foo = 22; // y.foo also = 22 since y and x are the same object 

如果你想obj.key != jsonobj,你需要克隆的對象。通過創建一個新的對象:

obj.key = $.parseJSON(objstring); 

或使用jQuery克隆現有的一個:

obj.key = $.extend({}, jsonobj); 
+0

但我似乎沒有找到第二個日誌的輸出背後的答案.......... –

+0

根據Domenic的回答,第二個日誌語句是錯誤的。如果你想要一個有效的console.log:'console.log(JSON.stringify(jsonobj))' –

5

我想解決的一小塊東西是怎麼回事,因爲別人已經做得這麼好處理JavaScript對象引用的更大的問題:

// second console output 
console.log(jsonobj); 

obj.key = jsonobj; 
obj.key.test = "why does this affect jsonobj? (even in the second console output)"; 

這是一個documented WebKit bug的結果,console.log語句在調用console.log時不輸出對象,而是在稍後的一段時間。

+0

我試圖讓這個時候我得到的東西更加清晰,所以請解釋任何-1票... – Domenic

+0

哦,好吧,這隻會導致我以前錯誤地理解javascript如何處理對象複製/委託。感謝你指出這一點;)。 – Hans

+0

將我的-1更改爲+1。在我投票的時候,你沒有詳細的答案。現在我的臉上有雞蛋。 – used2could

相關問題