关于javascript:使用jquery(deep)复制数组

(Deep) copying an array using jQuery

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What is the most efficient way to clone a JavaScript object?

我需要复制一个(有序的,非关联的)对象数组。我正在使用jquery。我刚试过

1
jquery.extend({}, myArray)

但是,很自然,这会给我一个对象,在那里我需要一个数组(顺便说一下,我非常喜欢jquery.extend)。

那么,复制数组的最佳方法是什么?


由于array.slice()不进行深度复制,因此不适用于多维数组:

1
2
3
4
5
var a =[[1], [2], [3]];
var b = a.slice();

b.shift().shift();
// a is now [[], [2], [3]]

请注意,尽管我在上面使用了shift().shift(),但重点是b[0][0]包含指向a[0][0]的指针,而不是值。

同样,delete(b[0][0])也会导致a[0][0]被删除,b[0][0]=99也会将a[0][0]的值更改为99。

jquery的extend方法在将真值作为初始参数传递时执行深度复制:

1
2
3
4
5
var a =[[1], [2], [3]];
var b = $.extend(true, [], a);

b.shift().shift();
// a is still [[1], [2], [3]]


$.extend(true, [], [['a', ['c']], 'b'])

那应该为你做。


我知道你在寻找一个数组的"深度"副本,但是如果你只有一个单层数组,你可以使用它:

复制本机JS数组很容易。使用array.slice()方法创建数组的部分/全部副本。

1
2
var foo = ['a','b','c','d','e'];
var bar = foo.slice();

现在foo和bar是"a"、"b"、"c"、"d"、"e"的5个成员数组

当然,酒吧是复制品,不是参考…所以如果你下一步这么做…

1
2
3
bar.push('f');
alert('foo:' + foo.join(', '));
alert('bar:' + bar.join(', '));

你现在可以得到:

1
2
foo:a, b, c, d, e
bar:a, b, c, d, e, f


javascript中的所有内容都是通过引用传递的,因此如果您想要数组中对象的真正深度副本,我能想到的最好方法是将整个数组序列化为JSON,然后将其反序列化。


如果要使用纯javascript,请尝试以下操作:

1
2
3
4
5
6
7
8
9
10
 var arr=["apple","ball","cat","dog"];
 var narr=[];

 for(var i=0;i<arr.length;i++){
     narr.push(arr[i]);
 }
 alert(narr); //output: apple,ball,vat,dog
 narr.push("elephant");
 alert(arr); // output: apple,ball,vat,dog
 alert(narr); // apple,ball,vat,dog,elephant

复杂类型呢?当数组包含对象时…或者别的什么

我的变体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Object.prototype.copy = function(){
    var v_newObj = {};
    for(v_i in this)
        v_newObj[v_i] = (typeof this[v_i]).contains(/^(array|object)$/) ? this[v_i].copy() : this[v_i];
    return v_newObj;
}

Array.prototype.copy = function(){
    var v_newArr = [];
    this.each(function(v_i){
        v_newArr.push((typeof v_i).contains(/^(array|object)$/) ? v_i.copy() : v_i);
    });
    return v_newArr;
}

这不是最终版本,只是一个想法。

PS:每个方法和包含的方法也是原型。


我计划在JPAQ的下一个版本中发布此代码,但在此之前,如果您的目标是对数组进行深度复制,则可以使用此代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Array.prototype.clone = function(doDeepCopy) {
    if(doDeepCopy) {
        var encountered = [{
            a : this,
            b : []
        }];

        var item,
            levels = [{a:this, b:encountered[0].b, i:0}],
            level = 0,
            i = 0,
            len = this.length;

        while(i < len) {
            item = levels[level].a[i];
            if(Object.prototype.toString.call(item) ==="[object Array]") {
                for(var j = encountered.length - 1; j >= 0; j--) {
                    if(encountered[j].a === item) {
                        levels[level].b.push(encountered[j].b);
                        break;
                    }
                }
                if(j < 0) {
                    encountered.push(j = {
                        a : item,
                        b : []
                    });
                    levels[level].b.push(j.b);
                    levels[level].i = i + 1;
                    levels[++level] = {a:item, b:j.b, i:0};
                    i = -1;
                    len = item.length;
                }
            }
            else {
                levels[level].b.push(item);
            }

            if(++i == len && level > 0) {
                levels.pop();
                i = levels[--level].i;
                len = levels[level].a.length;
            }
        }

        return encountered[0].b;
    }
    else {
        return this.slice(0);
    }
};

下面是如何调用此函数来执行递归数组的深度复制的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Create a recursive array to prove that the cloning function can handle it.
var arrOriginal = [1,2,3];
arrOriginal.push(arrOriginal);

// Make a shallow copy of the recursive array.
var arrShallowCopy = arrOriginal.clone();

// Prove that the shallow copy isn't the same as a deep copy by showing that
// arrShallowCopy contains arrOriginal.
alert("It is" + (arrShallowCopy[3] === arrOriginal)
    +" that arrShallowCopy contains arrOriginal.");

// Make a deep copy of the recursive array.
var arrDeepCopy = arrOriginal.clone(true);

// Prove that the deep copy really works by showing that the original array is
// not the fourth item in arrDeepCopy but that this new array is.
alert("It is"
    + (arrDeepCopy[3] !== arrOriginal && arrDeepCopy === arrDeepCopy[3])
    +" that arrDeepCopy contains itself and not arrOriginal.");

您可以在JSBin中使用此代码。


我遇到了这个"深度对象复制"功能,它可以方便地按值复制对象。它不使用jquery,但它确实很深。

http://www.overset.com/2007/07/11/javascript-recursive-object-copy-deep-object-copy-pass-by-value/