将JavaScript中的数组复制到另一个数组时:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
我意识到arr2指的是与arr1相同的数组,而不是一个新的独立数组。如何复制阵列以获得两个独立的阵列?
将JavaScript中的数组复制到另一个数组时:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
我意识到arr2指的是与arr1相同的数组,而不是一个新的独立数组。如何复制阵列以获得两个独立的阵列?
当前回答
当我们想要使用赋值运算符(=)复制数组时,它不会创建副本,只会复制指向数组的指针/引用。例如:
常量oldArr=[1,2,3];const newArr=旧Arr;//现在oldArr指向内存中的相同位置console.log(oldArr==newArr);//指向内存中的相同位置,因此是正确的常量拷贝=[1,2,3];console.log(copy==newArr);//不指向内存中的相同位置,因此是错误的
通常,当我们转换数据时,我们希望保持初始数据结构(例如数组)的完整性。我们通过制作数组的精确副本来实现这一点,这样可以在初始数组保持不变的情况下转换该数组。
复制阵列的方法:
常量oldArr=[1,2,3];//使用扩展运算符将旧值扩展到新数组文本中const newArr1=[…oldArr];//不带参数的切片返回新复制的数组const newArr2=oldArr.slice();//Map将回调应用于数组中的每个元素并返回一个新数组const newArr3=旧Arr.map((el)=>el);//Concat用于合并数组并返回一个新数组。不带参数的凹形复制数组const newArr4=oldArr.contat();//Object.assign可用于将所有财产转换为新的数组文字const newArr5=对象赋值([],oldArr);//使用new关键字通过Array构造函数创建const newArr6=新数组(…oldArr);//For循环函数克隆(基本){常量newArray=[];for(设i=0;i<base.length;i++){newArray[i]=基[i];}return newArray;}const newArr7=克隆(oldArr);console.log(newArr1、newArr2、newArr3、newArr4、newArr5、newArr6、newArr7);
嵌套数组或对象时要小心!:
嵌套数组时,将通过引用复制值。以下是一个示例,说明这可能会导致问题:
设arr1=[1,2,[1,2]]设arr2=[…arr1];arr2[2][0]=5;//我们改变arr2console.log(arr1);//arr1也被更改,因为arr1内部的数组是通过引用复制的
因此,当数组中存在要复制的对象或数组时,不要使用这些方法。即,仅在基元数组上使用这些方法。
如果您确实想深度克隆javascript数组,请将JSON.parse与JSON.stringify结合使用,如下所示:
设arr1=[1,2,[1,2]]让arr2=JSON.parse(JSON.stringify(arr1));arr2[2][0]=5;console.log(arr1);//现在我没有被修改,因为我是一个深度克隆
复制性能:
因此,我们选择哪一种来获得最佳性能。结果证明,最冗长的方法,for循环具有最高的性能。使用for循环进行真正的CPU密集型复制(大/多阵列)。
在此之后,.slice()方法也有不错的性能,而且不那么冗长,程序员更容易实现。我建议将.slice()用于日常复制不太占用CPU的数组。如果不需要深度克隆,并且性能存在问题,还应避免使用JSON.parse(JSON.stringify(arr))(大量开销)。
源性能测试
其他回答
正如我们在Javascript中所知道的那样,数组和对象都是通过引用的,但是我们可以用什么方法复制数组而不改变后面的原始数组呢?
这里有几种方法:
假设我们在您的代码中有这个数组:
var arr = [1, 2, 3, 4, 5];
1) 在函数中循环数组并返回一个新数组,如下所示:
function newArr(arr) {
var i=0, res = [];
while(i<arr.length){
res.push(arr[i]);
i++;
}
return res;
}
2) 使用slice方法,slice用于对数组的一部分进行切片,它将在不接触原始数组的情况下对数组的某些部分进行切片。在切片中,如果不指定数组的开始和结束,它将对整个数组进行切片,并基本上制作数组的完整副本,因此我们可以很容易地说:
var arr2 = arr.slice(); // make a copy of the original array
3) 还有contact方法,这是用于合并两个数组,但我们可以只指定其中一个数组,然后这基本上会复制新接触数组中的值:
var arr2 = arr.concat();
4) 另外,不建议使用stringify和parse方法,但这是复制Array和Objects的一种简单方法:
var arr2 = JSON.parse(JSON.stringify(arr));
5) Array.from方法,这不受广泛支持,使用前请检查不同浏览器中的支持:
const arr2 = Array.from(arr);
6) ECMA6方式,也不完全支持,但babelJs可以帮助您,如果您想转换:
const arr2 = [...arr];
您可以将ES6与spread Opartor一起使用,它更简单。
arr2 = [...arr1];
有一些限制。。check docs Spread语法@mozilla
如果您在ECMAScript 6环境中,使用Spread Operator,您可以这样做:
var arr1=[‘a’,‘b’,‘c’];var arr2=[…arr1]//复制arr1arr2.推('d');控制台日志(arr1)控制台日志(arr2)<script src=“http://www.wzvang.com/snippet/ignore_this_file.js“></script>
对于包含对象的ES6阵列
cloneArray(arr) {
return arr.map(x => ({ ...x }));
}
我个人认为Array.from是一个更具可读性的解决方案。顺便说一句,请注意它的浏览器支持。
//克隆设x=[1,2,3];设y=数组.来自(x);console.log({y});//深层克隆让clone=arr=>Array.from(arr,item=>Array.isArray(item)?克隆(项目):项目);x=[1,[],[[]]];y=克隆(x);console.log({y});