创建多维数组的副本,而不是引用—JavaScript [duplicate]

时间:2021-01-23 21:38:09

Possible Duplicate:
What is the most efficient way to clone a JavaScript object?

可能的重复:克隆JavaScript对象最有效的方法是什么?

This is also referred to as "deep copying", which I've found some articles on. Closest seems to be this one but it's for jQuery - I'm trying to do this without a library.

这也被称为“深度复制”,我在上面找到了一些文章。最接近的似乎是这个,但它是针对jQuery的——我尝试在没有库的情况下做到这一点。

I've also seen, in two places, that it's possible to do something like:

我也在两个地方看到,做一些事情是可能的,比如:

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

But that's apparently inefficient. It's also possible to loop and copy each value individually, and recurs through all the arrays. That seems tiring and inefficient as well.

但这显然是低效的。也可以分别循环和复制每个值,并在所有数组中重复出现。这看起来既累又低效。

So what's the most efficient, non-library way to copy a JavaScript multi-dimensional array [[a],[b],[c]]? I am completely happy with a "non-IE" method if necessary.

那么,复制JavaScript多维数组[a]、[b]、[c]最有效的非库方法是什么?如果有必要的话,我完全喜欢“非ie”方法。

Thanks!

谢谢!

4 个解决方案

#1


43  

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().

由于看起来您处理的数组的深度未知,但是您只需要在任何给定时间的一个深度处理它们,那么使用.slice()将会非常简单和快速。

var newArray = [];

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

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

或使用.map()代替for循环:

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.

当然,如果数组和其他数据混合在一起,您需要在切片之前测试它是什么。

#2


5  

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

我不知道JSON有多好。线和JSON。解析而不是编码和解码,但您可以尝试:

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

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

#3


4  

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-dimensioanl array, it simply would look like this:

当您要求性能时,我猜您还将使用非泛型解决方案。要复制具有已知级别的多维数组,您应该使用最简单的解决方案,即一些嵌套的for循环。对于你的二维anl数组,它看起来很简单:

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

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.

本机切片方法比定制的for循环更有效,但它不会创建深层副本,因此我们只能在最低级别使用它。

#4


3  

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.

任何不访问同一节点两次的递归算法的效率都将与使用javascript(至少在浏览器中)的效率相当——在其他语言的某些情况下,您可能不需要复制内存,但javascript显然没有这种能力。

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.

我建议找一个已经这样做过的人,并使用他们的实现来确保您做对了——它只需要定义一次。

#1


43  

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().

由于看起来您处理的数组的深度未知,但是您只需要在任何给定时间的一个深度处理它们,那么使用.slice()将会非常简单和快速。

var newArray = [];

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

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

或使用.map()代替for循环:

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.

当然,如果数组和其他数据混合在一起,您需要在切片之前测试它是什么。

#2


5  

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

我不知道JSON有多好。线和JSON。解析而不是编码和解码,但您可以尝试:

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

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

#3


4  

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-dimensioanl array, it simply would look like this:

当您要求性能时,我猜您还将使用非泛型解决方案。要复制具有已知级别的多维数组,您应该使用最简单的解决方案,即一些嵌套的for循环。对于你的二维anl数组,它看起来很简单:

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

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.

本机切片方法比定制的for循环更有效,但它不会创建深层副本,因此我们只能在最低级别使用它。

#4


3  

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.

任何不访问同一节点两次的递归算法的效率都将与使用javascript(至少在浏览器中)的效率相当——在其他语言的某些情况下,您可能不需要复制内存,但javascript显然没有这种能力。

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.

我建议找一个已经这样做过的人,并使用他们的实现来确保您做对了——它只需要定义一次。