在JavaScript中克隆多维数组

4

我希望能够克隆多维数组,这样我就可以在不影响主数组的情况下操作克隆数组。

我使用以下函数来实现:

Array.prototype.clone = function () { 
   var newArray = new Array(this.length);
     for(var i=0; i < this.length; i++ ){
        newArray[i] = this[i];
   }
   return newArray;
};

但是问题在于它使用了数组原型,因此它会克隆我所有的数组。那么有没有人能告诉我最好的解决方法呢?

3个回答

10

vsync是正确的,我的第一个回答没有处理var a = [[1,2],[3,4]];
因此这是一个改进版本

var a = [[1,2],[3,4]];
Array.prototype.clone = function() {
    var arr = this.slice(0);
    for( var i = 0; i < this.length; i++ ) {
        if( this[i].clone ) {
            //recursion
            arr[i] = this[i].clone();
        }
    }
    return arr;
}

var b = a.clone()

console.log(a);
console.log(b);

b[1][0] = 'a';

console.log(a);
console.log(b);

//[[1, 2], [3, 4]]
//[[1, 2], [3, 4]]
//[[1, 2], [3, 4]]
//[[1, 2], ["a", 4]]

第一个答案对我来说没有正常工作,但这个答案完美地解决了问题。谢谢! - Chris Porter
2
非常感谢您在此发布这种方法。我对它进行了另一项改进:if( this[i] && this[i].clone ) { 以支持 稀疏 数组(或者当某些值为 null 时称之为其他名称)。 - michael667

5

您需要使用递归

var a = [1,2,[3,4,[5,6]]];

Array.prototype.clone = function() {
    var arr = [];
    for( var i = 0; i < this.length; i++ ) {
//      if( this[i].constructor == this.constructor ) {
        if( this[i].clone ) {
            //recursion
            arr[i] = this[i].clone();
            break;
        }
        arr[i] = this[i];
    }
    return arr;
}

var b = a.clone()

console.log(a);
console.log(b);

b[2][0] = 'a';

console.log(a);
console.log(b);

/*
[1, 2, [3, 4, [5, 6]]]
[1, 2, [3, 4, [5, 6]]]
[1, 2, [3, 4, [5, 6]]]
[1, 2, ["a", 4, [5, 6]]]
*/

然而,原始数组中的其他对象将通过引用进行复制。


你可以检查数组中每个对象是否存在 clone 方法,如果存在则调用该方法进行克隆。这将处理数组的递归,并且也允许任何其他具有克隆方法的对象进行深度复制。 - Daniel Earwicker
1
它无法正确地克隆这样的内容:var a = [[1,2],[3,4]]; - vsync

4

我发现这种方法比meouw的更好:

var source = [
  [1, 2, {c:1}],
  [3, 4, [5, 'a']]
];

// Create a new method ontop of the "Array" primitive prototype:
Array.prototype.clone = function() {
  function isArr(elm) {
    return String(elm.constructor).match(/array/i) ? true : false;
  }

  function cloner(arr) {
    var arr2 = arr.slice(0),
        len = arr2.length;

    for (var i = 0; i < len; i++)
      if (isArr(arr2[i]))
        arr2[i] = cloner(arr2[i]);

    return arr2;
  }
  return cloner(this);
}

// Clone
var copy = source.clone();

// modify copy
copy[0][0] = 999;

console.dir(source);
console.dir('**************');
console.dir(copy);

另一种方法,只适用于具有原始值作为值的数据集(字符串数字对象):

var source = [
  [1,2, {a:1}],
  ["a", "b", ["c", 1]]
];

// clone "srouce" Array
var copy = JSON.parse(JSON.stringify(source));

// modyfy clone
copy[0][0] = 999;

// print both arrays
console.dir(copy)
console.log('***********')
console.dir(source)


我已经发布了一个改进的答案 :) - meouw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接