2009-02-19 64 views
178
数组

可能重复:
What is the most efficient way to clone a JavaScript object?(深)复制使用jQuery

我需要复制对象的(有序,不关联)阵列。我正在使用jQuery。我最初尝试

jquery.extend({}, myArray) 

但是,当然,这给我回一个对象,我需要一个数组(真的爱jquery.extend,顺便说一句)。

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

+0

如果你不想在返回一个对象,然后指定`[]`而不是`{}` – Ashwin 2017-11-07 08:33:21

回答

261

由于Array.slice()不会做深度复制,它是不适合多维数组:

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方法时,真正的价值作为初始参数传递执行深层副本:

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

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

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

这应该为你做。

+0

这不会对多维数组工作,你必须使用“真”作为第一个参数,通过在答复中提到@Noah Sussman – 2016-12-30 07:00:07

16

我知道你正在寻找一个数组的“深”的副本,但如果你只是有一个单级阵列您可以使用此:

复制原生JS数组是很容易。使用Array.slice()方法创建阵列的部分/全部副本。

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

现在foo和bar是 '一', 'B', 'C', 'd', 'E'

当然巴

的5个成员阵列是一个副本,而不是参考。 ..所以,如果你这样做下一个...

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

现在你会得到:

foo:a, b, c, d, e 
bar:a, b, c, d, e, f 
+24

请注意,这不是一个深层复制。 – 2012-05-07 15:38:02

+0

similar:var a = [1,2,3]; var b =([])。concat(a); b是副本 – 2012-05-07 15:38:35

+4

Array.slice不提供深层副本,这非常明确地是此处要问的问题。 – Ryley 2012-06-13 20:27:10

12

在JavaScript中的一切都是通过引用传递的,所以如果你想在数组中的对象的真实深拷贝,我能想到的最好的方法是序列化整个数组到JSON,然后去将它序列化。

2

我打算释放在jPaq下一版本的代码,但在那之前,你可以利用这一点,如果你的目标是做阵列的深层副本:

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); 
    } 
}; 

下面是如何调用这个函数来执行递归阵列的深层副本的例子:

// 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."); 

你可以玩这个代码here at JS Bin

5

如果你想使用纯JavaScript那就试试这个:

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

怎么样复杂类型? 当数组包含对象......或任何其他

我的变种:

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:方法中的每个,并含有是原型也。