2013-05-12 43 views
11

jsFiddle herejquery.extend(true,[],obj)不創建深度複製

如果深度複製工作,輸出將是「好奇的喬治」,而不是「恩德的遊戲」。我怎樣才能做一個深層複製?對this question的回答表示$.extend(true, [], obj)創建了一個深層副本。然而我的例子表明它沒有。

function Person(){} 
Person.prototype.favorite_books = []; 

var george = new Person(); 
george.favorite_books = ["Curious George"]; 

var kate = new Person(); 
kate.favorite_books = ["The Da Vinci Code", "Harry Potter"]; 

var people = [kate, george]; 

var people_copy = $.extend(true, [], people); 
people_copy[0].favorite_books[0] = "Ender's Game"; 

$('#text').text(people[0].favorite_books[0]); 

SOLUTION

我更新的jsfiddle。事實證明,如果對象是自定義對象(即,$.isPlainObject返回false),我需要深度複製陣列中的每個對象

+0

使用.clone()請參閱http://api.jquery.com/clone/ – 2013-05-12 22:44:11

+6

@Paul Sullivan:'.clone()'將與DOM實體 – zerkms 2013-05-12 22:44:44

+0

一起使用,所以請瀏覽.extend源代碼並查看原因遞歸函數不復制屬性 – 2013-05-12 22:45:48

回答

17

而現在這裏是真正答案:

目前的jQuery只可以克隆普通的JavaScript對象,而你使用自定義的。這很明顯,因爲jQuery不知道如何實例化一個新的自定義對象。因此,這按預期工作:

var george = {}; 
george.favorite_books = ["Curious George"]; 

var kate = {}; 
kate.favorite_books = ["The Da Vinci Code", "Harry Potter"]; 

var people = [kate, george]; 

var people_copy = $.extend(true, [], people); 

console.log(people_copy[0].favorite_books == people[0].favorite_books); 

參考到jQuery代碼:https://github.com/jquery/jquery/blob/master/src/core.js#L305

看到它檢查它是否jQuery.isPlainObject(copy)或者它是一個數組。否則它只執行參考副本。

+0

@Rose Perrone:因爲您創建了一個深層副本。所以原始對象保持原樣,並且修改的對象被獨立修改。不知道什麼讓你感到困惑。 – zerkms 2013-05-12 23:43:47

+0

@RoyiNamir你指定它應該是一個深層副本(第一個參數) – zerkms 2015-09-07 19:57:07

+0

請檢查'$ .extend'函數調用的第一個布爾參數意味着什麼。並問另一個問題,如果它仍然不清楚。 – zerkms 2015-09-07 21:31:47

2

有趣的....它看起來並不像它深拷貝數組。

您必須單獨深度複製每個對象。

var people_copy = []; 
$.each(people,function(i,obj) { 
    people_copy.push($.extend(true,{},obj)); 
}); 

編輯:當然,看這個叉子OP的小提琴:

http://jsfiddle.net/s2bLv/4/

+0

「深拷貝對象,而不是數組」---對此的任何證明?不是數組的一種特殊對象嗎? – zerkms 2013-05-12 22:49:33

+0

https://github.com/jquery/jquery/blob/master/src/core。js#L305 - 它應該處理數組 – zerkms 2013-05-12 22:53:02

+0

如果您必須單獨深度複製每個對象,您需要一些遞歸代碼來複制一切 - 除非這只是爲了覆蓋OP的簡單測試用例,而不是一個通用的解決方案? – nnnnnn 2013-05-12 22:55:33

7

這是我怎麼想很多方法後做到了:

var newArray = JSON.parse(JSON.stringify(orgArray)); 

這將創建一個新的深拷貝,而不是一個淺拷貝。此外,這顯然不會克隆事件和函數,但好處是你可以在一行中完成它,它可以用於任何對象(數組,字符串,數字,對象等)。

+2

它不適用於日期對象。 – 2015-01-07 21:01:21