可能是重复问题:
什么是克隆JavaScript对象最有效的方法?
我需要复制一个(有序,非关联)的对象数组。我正在使用jQuery。我最初尝试了
jquery.extend({}, myArray)
但是,自然地,这会给我返回一个对象,而我需要一个数组(顺便说一句,我真的很喜欢jQuery.extend)。
那么,复制一个数组的最佳方式是什么?
可能是重复问题:
什么是克隆JavaScript对象最有效的方法?
我需要复制一个(有序,非关联)的对象数组。我正在使用jQuery。我最初尝试了
jquery.extend({}, myArray)
但是,自然地,这会给我返回一个对象,而我需要一个数组(顺便说一句,我真的很喜欢jQuery.extend)。
那么,复制一个数组的最佳方式是什么?
由于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。extend
方法执行深度复制: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()方法即可创建数组的全部或部分副本。
var foo = ['a','b','c','d','e'];
var bar = foo.slice();
现在,foo和bar是包含'a'、'b'、'c'、'd'、'e'这五个成员的数组。
当然,bar是一个副本而不是一个引用... 所以如果你接下来执行了这个操作...
bar.push('f');
alert('foo:' + foo.join(', '));
alert('bar:' + bar.join(', '));
你现在将会得到:
foo:a, b, c, d, e
bar:a, b, c, d, e, f
JavaScript 中的所有内容都是按引用传递的,因此如果您想要数组中对象的真正深层副本,我能想到的最好方法是将整个数组序列化为 JSON,然后再进行反序列化。
如果想使用纯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
关于复杂类型怎么处理呢?当数组包含对象或其他数据类型时...
我的建议:
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:方法 each 和 contains 也是原型。
我计划在下一个版本的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.");
http://www.overset.com/2007/07/11/javascript-recursive-object-copy-deep-object-copy-pass-by-value/
[]
代替{}
。 - Ashwin