(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]] |
请注意,尽管我在上面使用了
同样,
jquery的
1 2 3 4 5 | var a =[[1], [2], [3]]; var b = $.extend(true, [], a); b.shift().shift(); // a is still [[1], [2], [3]] |
那应该为你做。
我知道你在寻找一个数组的"深度"副本,但是如果你只有一个单层数组,你可以使用它:
复制本机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/