【问题标题】:jquery.extend(true, [], obj) not creating a deep copyjquery.extend(true, [], obj) 不创建深拷贝
【发布时间】:2013-05-06 22:32:30
【问题描述】:

jsFiddle here.

如果深度复制有效,输出将是“Curious George”而不是“Ender's Game”。如何制作深拷贝?对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]);

解决方案

我更新了 jsFiddle。事实证明,我需要单独深度复制数组中的每个对象如果对象是自定义对象(即,$.isPlainObject 返回 false)。

【问题讨论】:

  • 使用 .clone() 见api.jquery.com/clone
  • @Paul Sullivan: .clone() 用于 DOM 实体
  • 好的,所以浏览 .extend 源代码,看看为什么递归函数不复制属性
  • @karthikr:你读过这个问题和你提到的答案吗?
  • "事实证明我需要对数组中的每个对象单独进行深度复制。" ...如果您是自定义对象

标签: javascript jquery


【解决方案1】:

这是我尝试了很多方法后的做法:

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

这将创建一个新的深层副本,而不是浅层副本。

同样这显然不会克隆事件和函数,但好处是你可以在一行中完成,它可以用于任何对象之王(数组、字符串、数字、对象等)。

【讨论】:

    【解决方案2】:

    现在这是真正的答案:

    目前 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) 还是一个数组。否则它只执行一个参考副本。

    【讨论】:

    • @Rose Perrone:因为您创建了一个深层副本。所以原始对象保持原样,修改后的对象独立修改。不确定是什么让您感到困惑。
    • @RoyiNamir 您指定它应该是深拷贝(第一个参数)
    • 请检查$.extend函数调用中的第一个布尔参数是什么意思。如果您还不清楚,请再问一个问题。
    【解决方案3】:

    有趣....它看起来不像是深拷贝数组。

    您必须单独深度复制每个对象。

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

    编辑:当然,看看 OP 小提琴的这个分支:

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

    【讨论】:

    • “深度复制对象,而不是数组”——有什么证据吗?数组不是一种特殊的对象吗?
    • 如果您必须单独深度复制每个对象,您将需要一些递归代码来一直复制 - 除非这只是为了涵盖 OP 的简单测试用例而不是通用解决方案?
    猜你喜欢
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2011-04-26
    • 2016-12-25
    • 2013-04-06
    • 2011-08-18
    相关资源
    最近更新 更多