如何在Javascript中克隆对象数组?

如何在Javascript中克隆对象数组?,javascript,Javascript,…其中每个对象还具有对同一数组中其他对象的引用 当我第一次提出这个问题时,我只是想到 var clonedNodesArray = nodesArray.clone() 将存在并搜索有关如何在javascript中克隆对象的信息。我确实发现了一个关于StackOverflow的问题(由同一个@JohnResig回答),他指出,使用jQuery可以做到这一点 var clonedNodesArray = jQuery.extend({}, nodesArray); 克隆一个对象。不过我尝试了这

…其中每个对象还具有对同一数组中其他对象的引用

当我第一次提出这个问题时,我只是想到

var clonedNodesArray = nodesArray.clone()
将存在并搜索有关如何在javascript中克隆对象的信息。我确实发现了一个关于StackOverflow的问题(由同一个@JohnResig回答),他指出,使用jQuery可以做到这一点

var clonedNodesArray = jQuery.extend({}, nodesArray);
克隆一个对象。不过我尝试了这个方法,它只复制数组中对象的引用。所以如果我

nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"
NodeArray[0]和ClonedNodeArray[0]的值都将变为“绿色”。然后我试着

var clonedNodesArray = jQuery.extend(true, {}, nodesArray);
它深度复制了一个对象,但我分别从Firebug和Opera Dragonfly获得了“太多递归”和“控制堆栈溢出”消息


你会怎么做?这是不应该做的事吗?在Javascript中是否有一种可重用的方法来执行此操作?

Array.slice可用于复制数组或数组的一部分。。 这将适用于字符串和数字更改一个数组中的字符串不会影响另一个数组,但对象仍然只是通过引用进行复制,因此更改一个数组中的引用对象会影响另一个数组


下面是一个JavaScript撤消管理器的示例,它在这方面可能很有用:

浅拷贝的问题是没有克隆所有对象。虽然对每个对象的引用在每个数组中都是唯一的,但一旦您最终抓住它,您就会像以前一样处理同一个对象。你克隆它的方式没有问题。。。使用Array.slice()也会产生相同的结果

深度副本出现问题的原因是,最终会出现循环对象引用。Deep将尽可能地深入,如果你有一个圆圈,它将无限继续,直到浏览器晕倒

如果数据结构不能表示为有向无环图,那么我不确定您是否能够找到一种用于深度克隆的通用方法。循环图提供了许多棘手的情况,由于它不是一个常见的操作,我怀疑是否有人编写了完整的解决方案(如果可能的话,可能没有!但我现在没有时间尝试编写严格的证明)。我在网上找到了一些关于这个问题的好评论

如果您需要具有循环引用的对象数组的深度副本,我相信您必须编写自己的方法来处理专门的数据结构,以便它是一个多过程克隆:

  • 在第一轮中,克隆不引用阵列中其他对象的所有对象。跟踪每个对象的原点
  • 在第二轮中,将对象链接在一起
    正如Daniel Lew提到的,循环图有一些问题。如果我有这个问题,我会向有问题的对象添加特殊的
    clone()
    方法,或者记住我已经复制了哪些对象

    我会使用一个变量
    copyCount
    ,它会在每次复制代码时增加1。复制的对象的拷贝数小于当前复制进程的拷贝数。如果没有,则应引用已存在的副本。这就需要从原件链接到副本


    还有一个问题:内存。如果从一个对象到另一个对象有此引用,则浏览器可能无法释放这些对象,因为它们总是从某个位置引用。您必须进行第二次传递,将所有副本引用设置为Null。(如果你这样做,你就不必有
    copyCount
    ,但是一个布尔
    isCopied
    就足够了,因为你可以在第二遍中重置值。)

    我可能有一个简单的方法来做这件事,而不必进行痛苦的递归,也不知道所讨论对象的所有细节。使用jQuery,只需使用jQuery
    $.toJSON(myObjectArray)
    将对象转换为JSON,然后将JSON字符串计算回对象。砰!完成了,完成了!问题已解决。:)


    如果您只需要一个浅拷贝,那么一个非常简单的方法是:

    new_array = old_array.slice(0);
    
    忘记eval()和slice(0)(仅适用于简单数据类型)

    这是我的最佳解决方案:

    Object.prototype.clone = function() {
      var myObj = (this instanceof Array) ? [] : {};
      for (i in this) {
        if (i != 'clone') {
            if (this[i] && typeof this[i] == "object") {
              myObj[i] = this[i].clone();
            } else 
                myObj[i] = this[i];
            } 
        }
      return myObj;
    };
    
    使用jQuery:

    var target= [];
    $.each(source, function() {target.push( $.extend({},this));});
    

    这个问题让我很沮丧。显然,当您向$.extend方法发送泛型数组时,问题就出现了。因此,为了修复它,我添加了一个小检查,它可以完美地用于泛型数组、jQuery数组和任何对象

    jQuery.extend({
        deepclone: function(objThing) {
            // return jQuery.extend(true, {}, objThing);
            /// Fix for arrays, without this, arrays passed in are returned as OBJECTS! WTF?!?!
            if ( jQuery.isArray(objThing) ) {
                return jQuery.makeArray( jQuery.deepclone($(objThing)) );
            }
            return jQuery.extend(true, {}, objThing);
        },
    });
    
    使用以下命令调用:

    var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
    // Or more simply/commonly
    var arrNewArrayClone = $.deepclone(arrOriginalArray);
    
    这对我很有用:

    var clonedArray = $.map(originalArray, function (obj) {
                          return $.extend({}, obj);
                      });
    
    如果需要阵列中对象的深度副本:

    var clonedArray = $.map(originalArray, function (obj) {
                          return $.extend(true, {}, obj);
                      });
    
    我的做法:

    var temp = { arr : originalArray };
    var obj = $.extend(true, {}, temp);
    return obj.arr;
    

    为我提供了一个漂亮、干净、深入的原始数组克隆,没有任何对象引用回原始数组:-)

    JQuery extend工作正常,只需指定克隆数组而不是对象(注意[]而不是{}作为extend方法的参数):


    以下代码将递归地执行以下操作:

    功能深度复制(obj){
    if(Object.prototype.toString.call(obj)='[Object Array]'){
    var out=[],i=0,len=obj.length;
    对于(;i

    我之所以回答这个问题,是因为对于“在Javascript中克隆对象数组”的问题似乎没有一个简单而明确的解决方案:

    功能深度复制(arr){
    var out=[];
    对于(变量i=0,len=arr.length;ivar clonedArray = $.map(originalArray, function (obj) {
                          return $.extend(true, {}, obj);
                      });
    
    var temp = { arr : originalArray };
    var obj = $.extend(true, {}, temp);
    return obj.arr;
    
    var clonedNodesArray = jQuery.extend([], nodesArray);
    
    function deepCopy(obj) {
    if (Object.prototype.toString.call(obj) === '[object Array]') {
        var out = [], i = 0, len = obj.length;
        for ( ; i < len; i++ ) {
            out[i] = arguments.callee(obj[i]);
        }
        return out;
    }
    if (typeof obj === 'object') {
        var out = {}, i;
        for ( i in obj ) {
            out[i] = arguments.callee(obj[i]);
        }
        return out;
    }
    return obj;
    }
    
    function deepCopy (arr) {
        var out = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            var item = arr[i];
            var obj = {};
            for (var k in item) {
                obj[k] = item[k];
            }
            out.push(obj);
        }
        return out;
    }
    
    // test case
    
    var original = [
        {'a' : 1},
        {'b' : 2}
        ];
    
    var copy = deepCopy(original);
    
    // change value in copy
    copy[0]['a'] = 'not 1';
    
    // original[0]['a'] still equals 1
    
    var clonedArray = JSON.parse(JSON.stringify(nodesArray))
    
    function deepClone (item) {
      if (Array.isArray(item)) {
        var newArr = [];
    
        for (var i = item.length; i-- !== 0;) {
          newArr[i] = deepClone(item[i]);
        }
    
        return newArr;
      }
      else if (typeof item === 'function') {
        eval('var temp = '+ item.toString());
        return temp;
      }
      else if (typeof item === 'object')
        return Object.create(item);
      else
        return item;
    }
    
    function deepClone (item) {
      if (Array.isArray(item)) {
        var newArr = [];
        for (var i = item.length; i-- > 0;) {
          newArr[i] = deepClone(item[i]);
        }
        return newArr;
      }
      if (typeof item === 'function' && !(/\(\) \{ \[native/).test(item.toString())) {
        var obj;
        eval('obj = '+ item.toString());
        for (var k in item) {
          obj[k] = deepClone(item[k]);
        }
        return obj;
      }
      if (item && typeof item === 'object') {
        var obj = {};
        for (var k in item) {
          obj[k] = deepClone(item[k]);
        }
        return obj;
      }
      return item;
    }
    
    const newArray = myArray.map(a => Object.assign({}, a));
    
    const newArray = myArray.map(a => ({...a}));
    
    var clonedObjArray = [...oldObjArray];
    
    const newArray=myArray.reduce((array, element)=>array.push(Object.assign({}, element)), []);
    
    var x = babel({}, obj)
    
    let oldObject = [1,3,5,"test"];
    let newObject = Object.assign({}, oldObject);
    
    let newObject = [...oldObject];
    
    let newArray = oldArray.map(a => {
                   let newObject = {};
                   Object.keys(a).forEach(propertyKey => {
                        newObject[propertyKey] = a[propertyKey];
                   });
                   return newObject ;
    });
    
    var objects = [{ 'a': 1 }, { 'b': 2 }];
    var deep = _.cloneDeep(objects);
    
    let a = [{ x:{z:1} , y: 2}];
    let b = JSON.parse(JSON.stringify(a));
    b[0].x.z=0
    
    console.log(JSON.stringify(a)); //[{"x":{"z":1},"y":2}]
    console.log(JSON.stringify(b)); // [{"x":{"z":0},"y":2}]
    
    person1 = {
        name: 'Naved',
        last: 'Khan',
        clothes: {
            jens: 5,
            shirts: 10
        }
    };
    
    person2 = {
        name: 'Naved',
        last: 'Khan'
    };
    
    // first way  shallow copy single lavel copy 
    // const person3 = { ...person1 };
    
    // secound way shallow copy single lavel copy
    // const person3 = Object.assign({}, person1);
    
    // third  way shallow copy single lavel copy but old 
    // const person3 = {};
    // for (let key in person1) {
    //  person3[key] = person1[key];
    // }
    
    // deep copy with array and object best way
    const person3 = JSON.parse(JSON.stringify(person1));
    
        person3.clothes.jens = 20;
    
    console.log(person1);
    console.log(person2);
    console.log(person3);