在 JavaScript 中的数组复制到另一个数组︰

var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d');  //Now, arr1 = ['a','b','c','d']

我意识到, arr2指的是与arr1,相同的阵列而不是一个新的、 独立的数组。如何复制阵列就可以使两个独立的数组?使用 jQuery 就更好了。

2011-09-20 13:38:08
问题评论:

回答:

使用此选项︰

var newArray = oldArray.slice();

基本上, slice()操作克隆数组并返回新的数组的引用。此外应注意︰

  • 对对象的引用 (并不是实际的对象),扇区复制到新的数组对象引用。同时原有和新数组引用同一个对象。如果引用的对象发生更改,则所做的更改可以看到新和原始数组。
  • 对于字符串和数字,切片到新的数组中复制字符串和数字。字符串或一个数组中的数字的更改不会影响其他数组。

指定0索引是 uneccessary

正确的但只需添加清晰度 (可读性)

我认为如果可读性的这一个问题,一个不使用原始slice操作。

我认为,在中放置一个 0 是一种样式并不性能或标准与相关参数是多余所以

尽管这已经收到大量的 upvotes,值得另一个因为它正确地描述中 JS,是有点少,但遗憾的是引用。

JavaScript 提供了几种不同类型的数组 (至少五种类型)。

var type1 = ['a', 'b']; // Array of String literals
var type2 = [1, 2]; // Array of Number literals
var type3 = [['a'], ['b']]; // Array of Arrays
var type4 = [{a: 'a'} , {b: 'b'}]; // Array of Object literals
var type5 = [{a: function () {}}, {b: function () {}}]; // Array of Objects

注意︰"文字"一词非常重要。在字符串和数字也可以创建为对象,并且仅文本版本属于 type1 和 type2 阵列。例如︰

var stringLiteral = 'stringLiteral'; // seen in type1 array
var stringObject = new String('stringLiteral'); // seen in type5 array
var numberLiteral = 1; // seen in type2 array
var numberObject = new Number(1); // seen in type5 array

取决于阵列类型 (type1、 type2 等),各种技术 (如.splice、.concat,JSON,$.extend,等等) 可以使用深层复制到一个数组。

myArray.splice(0);
myArray.slice();
myArray.concat();
JSON.parse(JSON.stringify(myArray));
$.extend(true, [], myArray); // jQuery
_.extend(); // underscore
_.cloneDeep(); // lo-dash

但是,大多数技术不深复制所有的数组类型。

(按数组类型) 的各种技术的深层副本支持 Deep-copy technique by array-type

  • 接头、 切片和连接可用于深复制数组的字符串和数字的数组文本;其中切片具有比连接更好的性能。http://jsperf.com/duplicate-array-slice-vs-concat/3.
  • JSON.parse(JSON.stringify()) 可用于深复制数组的字符串常值、 数组的数字文本、 数组的数组,和数组的对象文本-但不是数组的原型对象。
  • jQuery $.extend() 可用于深副本任何数组类型。其他库如下划线Lo 划线提供类似深副本功能,但是它们提供也慢。更出奇的是,$.extend 还具有更好的性能,比 JSON.parse(JSON.stringify()) http://jsperf.com/js-deep-copy/2.

深副本 (不含第三方库) 任何数组类型︰

对于那些不愿意使用第三方函数库 (如 jQuery) 的开发人员,您可以使用下面的自定义函数;所有数组类型都具有更快的性能比 $.extend 和深层副本。警告 !此解决方案是在 NodeJS 中有问题;深层复制的数组中的任何null对象将被转换为空的对象文本{}.

function copy(o) {
   var output, v, key;
   output = Array.isArray(o) ? [] : {};
   for (key in o) {
       v = o[key];
       output[key] = (typeof v === "object") ? copy(v) : v;
   }
   return output;
}

这样回答问题...

问题

var arr1 = ['a','b','c'];
var arr2 = arr1;

我意识到,arr2 指的是与 arr1,相同的阵列而不是一个新的、 独立的数组。如何复制阵列就可以使两个独立的数组?

答案

因为这是一个字符串的数组,它是 type1 阵列,并因此可以使用各种深副本技术,任一片能提供性能是最快的地方。

// Any of these techniques will deep-copy an Array of String literals

arr2 = arr1.slice();
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // custom-function needed, as provided above

Saket 的答案并不使用它使用slicesplice很大的不同

许多这些方法不能很好地工作。使用赋值运算符意味着,您必须重新分配arr1的原始文本值。它是非常少见的这将这种情况。因此,不是一个副本在所有使用spliceobliterates arr1如果数组中的值的任何函数或具有原型 (例如Date使用JSON将失败).

我认为这应该是正确的答案的问题。扇区,请连接有问题

为什么 splice(0)?它不应该是 slice()?我认为,按理不能修改原始数组,哪个接头不会。@JamesMontagne

接头将原始数组 (浅表副本) 中创建指向元素的指针。splice(0) 将为数字或字符串,并创建所有其他元素类型 (浅表副本) 的指针数组中的元素分配新的内存 (深层副本)。通过起始值为零的接合函数方法,它不会接合从原始数组的所有元素,因此它不会对其进行修改。

没有所需的 jQuery...使用示例

var arr2 = arr1.slice()

此复制数组中的起始位置0到数组的末尾。

值得注意的是,它将按预期方式工作为基元类型 (字符串、 数字等),并说明预期的行为,对于引用类型...

具有引用类型的数组,如果说的类型为Object数组被复制,但这两个数组将包含对同一Object的引用 ' s。因此在这种情况下看起来像数组复制通过即使引用数组实际复制。

感谢您的示例。我很好奇,这种类型的复制称为深层副本?

不这不是深层复制。

slice的替代方法是concat,它可以用两种方式。第一种可能是多如预期的行为是非常清楚易读︰

var array2 = [].concat(array1);

第二种方法是︰

var array2 = array1.concat();

Cohen (意见) 中的所指出的这后一种方法具有更好的性能.

此工作是concat方法创建由的对象调用它跟任何数组的元素中的元素的新数组的方法作为参数传递给它。因此当不传递任何参数时,它只是将复制数组。

Lee Penkman 还在注释,指出,如果没有机会array1undefined,您可以返回一个空数组,如下所示︰

var array2 = [].concat(array1 || []);

或者,对于第二种方法︰

var array2 = (array1 || []).concat();

请注意,您还可以执行这slicevar array2 = (array1 || []).slice();.

实际上,也可以做︰ var array2 = array1.concat();它是快了很多有关性能。(JSPerf: jsperf.com/copy-array-slice-vs-concat/5jsperf.com/副本-简单的数组

其 array1 值得注意的,如果不是数组,则[].concat(array1)如返回[array1]如果其未定义您将获得[undefined]我有时做var array2 = [].concat(array1 || []);

连接不会创建该对象的引用,但创建一个新数组。这是我的需要

在未来 (ES6) 可以使用数组跨页...复制数组。

const itemsCopy = [...items];

同时如果想要创建一个新数组,与现有成为它的一部分︰

var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];

如果您想要开始使用此现在可以使用 typescript 或混乱从而使,并编译成安全的 javascript。

在跨页上的详细信息

这应该是 upvoted

Hooray ES6 的答案。

内容来源于Stack Overflow Copying array by value in JavaScript
请输入您的翻译

Copying array by value in JavaScript

确认取消