2013-05-12 54 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