将JavaScript中的数组复制到另一个数组时:

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

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


当前回答

这里有一个变体:

var arr1=['a', 'b', 'c'];
var arr2=eval(arr1.toSource());
arr2.push('d');
console.log('arr1: '+arr1+'\narr2: '+arr2);
/*
 *  arr1: a,b,c
 *  arr2: a,b,c,d
 */

其他回答

切片的另一种选择是凹面,可以用两种方式。第一个可能更容易理解,因为预期行为非常清楚:

var array2 = [].concat(array1);

第二种方法是:

var array2 = array1.concat();

科恩(在评论中)指出,后一种方法具有更好的性能。

其工作方式是concat方法创建一个新数组,该数组由调用它的对象中的元素组成,后跟作为参数传递给它的任何数组的元素。因此,当没有传递参数时,它只是复制数组。

Lee Penkman也在评论中指出,如果array1有可能未定义,可以返回一个空数组,如下所示:

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

或者,对于第二种方法:

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

请注意,您也可以使用slice:var array2=(array1||[]).slice();执行此操作;。

只是在写:

arr2 = arr1.concat();

您正在使用第一个数组的副本生成新数组。请注意,这是将元素推入数组的一种功能方式。

如果您的代码基于ES6,您也可以使用扩展运算符:

arr2 = [...arr1];

var arr2=arr1.slice(0);

这种方法只适用于简单数组。

如果您有类似复杂阵列的对象阵列,则必须使用其他解决方案,如:

const arr2 = JSON.parse(JSON.stringify(arr1)); 

例如,我们有一个对象数组,每个单元格的对象中都有另一个数组字段。。。在这种情况下,如果我们使用切片方法,那么数组字段将通过Ref进行复制,这意味着这些字段更新将影响原始数组中的相同元素和字段。

let a = [1,2,3];

现在,您可以执行以下任一操作来创建阵列的副本。

let b = Array.from(a); 

OR

let b = [...a];

OR

let b = new Array(...a); 

OR

let b = a.slice(); 

OR

let b = a.map(e => e);

现在,如果我改变一个,

a.push(5); 

那么,a是[1,2,3,5],但b仍然是[1,3,3],因为它有不同的引用。

但我认为,在上述所有方法中,Array.from都更好,并且主要用于复制数组。

基本体值始终按其值传递(复制)。但是,复合值是通过引用传递的。

那么我们如何复制这个arr?

let arr = [1,2,3,4,5];

在ES6中复制阵列

let arrCopy = [...arr]; 

在ES5中复制n阵列

let arrCopy = arr.slice(); 
let arrCopy = [].concat(arr);

为什么“let arrCopy=arr”不按值传递?

将一个变量传递给另一个复合值(例如“对象/数组”)会有不同的行为。在共和值上使用sign运算符,我们将引用传递给对象。这就是为什么在删除/添加arr元素时,两个数组的值都会发生变化。

例外情况:

arrCopy[1] = 'adding new value this way will unreference';

为变量指定新值时,将更改引用本身,而不会影响原始对象/数组。

阅读更多信息