创建多维数组的副本,而不是引用-JavaScript

这也被称为“深度拷贝”,我在其中发现了一些文章。最接近的似乎是 这个,但它是为 jQuery-我试图在没有库的情况下做到这一点。

我还看到,在两个地方,有可能做类似的事情:

arr2 = JSON.decode(JSON.encode(arr1));

但这显然效率低下。还可以单独循环和复制每个值,并遍历所有数组。这看起来很累,效率也很低。

那么,复制 JavaScript 多维数组 [[a],[b],[c]]的最有效、非库的方法是什么呢?如果有必要,我非常乐意使用“非 IE”方法。

谢谢!

74688 次浏览

I'm not sure how much better JSON.stringify and JSON.parse than encode and decode, but you could try:

JSON.parse(JSON.stringify(array));

Something else I found (although I'd modify it a little):

http://www.xenoveritas.org/blog/xeno/the-correct-way-to-clone-javascript-arrays

function deepCopy(obj) {
if (typeof obj == 'object') {
if (isArray(obj)) {
var l = obj.length;
var r = new Array(l);
for (var i = 0; i < l; i++) {
r[i] = deepCopy(obj[i]);
}
return r;
} else {
var r = {};
r.prototype = obj.prototype;
for (var k in obj) {
r[k] = deepCopy(obj[k]);
}
return r;
}
}
return obj;
}

Any recursive algorithm that doesn't visit the same node twice will be about as efficient as you get with javascript (at least in a browser) - in certain situations in other languages you might get away with copying chucks of memory, but javascript obviously doesn't have that ability.

I'd suggest finding someone who's already done it and using their implementation to make sure you get it right - it only needs to be defined once.

Since it sounds like you're dealing with an Array of Arrays to some unknown level of depth, but you only need to deal with them at one level deep at any given time, then it's going to be simple and fast to use .slice().

var newArray = [];


for (var i = 0; i < currentArray.length; i++)
newArray[i] = currentArray[i].slice();

Or using .map() instead of the for loop:

var newArray = currentArray.map(function(arr) {
return arr.slice();
});

So this iterates the current Array, and builds a new Array of shallow copies of the nested Arrays. Then when you go to the next level of depth, you'd do the same thing.

Of course if there's a mixture of Arrays and other data, you'll want to test what it is before you slice.

As you asked for performance, I guess you also would go with a non-generic solution. To copy a multi-dimensional array with a known number of levels, you should go with the easiest solution, some nested for-loops. For your two-dimensional array, it simply would look like this:

var len = arr.length,
copy = new Array(len); // boost in Safari
for (var i=0; i<len; ++i)
copy[i] = arr[i].slice(0);

To extend to higher-dimensional arrays, either use recursion or nested for loops!

The native slice method is more efficient than a custom for loop, yet it does not create deep copies, so we can use it only at the lowest level.