2009-02-19 42 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:方法中的每個,並含有是原型也。