在 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
相同的数组,而不是一个新的独立数组。如何将数组复制以获得两个独立的数组?如果你处于 ECMAScript 6 环境中,可以使用 扩展运算符 来完成此操作:
var arr1 = ['a','b','c'];
var arr2 = [...arr1]; //copy arr1
arr2.push('d');
console.log(arr1)
console.log(arr2)
<script src="http://www.wzvang.com/snippet/ignore_this_file.js"></script>
那么我们如何复制这个 arr ?
let arr = [1,2,3,4,5];
let arrCopy = [...arr];
let arrCopy = arr.slice();
let arrCopy = [].concat(arr);
在复合值(如对象/数组)中将一个变量传递给另一个变量的行为是不同的。使用赋值运算符在复合值上,我们会传递一个指向对象的引用。这就是为什么在删除/添加arr元素时,两个数组的值都会发生变化。
arrCopy[1] = 'adding new value this way will unreference';
当你将一个新的值赋给变量时,你正在改变引用本身,这不会影响原始的对象/数组。
在解决 array.slice(); 问题时,需要注意如果你有多维数组,子数组将通过引用进行复制。你可以循环并逐个切片(slice())每个子数组。
var arr = [[1,1,1],[2,2,2],[3,3,3]];
var arr2 = arr.slice();
arr2[0][1] = 55;
console.log(arr2[0][1]);
console.log(arr[0][1]);
function arrCpy(arrSrc, arrDis){
for(elm in arrSrc){
arrDis.push(arrSrc[elm].slice());
}
}
var arr3=[];
arrCpy(arr,arr3);
arr3[1][1] = 77;
console.log(arr3[1][1]);
console.log(arr[1][1]);
同样的道理也适用于对象数组,它们将被引用复制,您需要手动复制它们。
let a = [1,2,3];
let b = Array.from(a);
或者
let b = [...a];
或者
let b = new Array(...a);
或者
let b = a.slice();
或者
let b = a.map(e => e);
a.push(5);
然后,a是[1,2,3,5],但b仍然是[1,2,3],因为它有不同的引用。
但我认为,在上述所有方法中Array.from是更好的选择,主要用于复制一个数组。
我个人更喜欢这种方式:
JSON.parse(JSON.stringify( originalObject ));
我发现这种方法相对较容易:
let arr = [1,2,3,4,5];
let newArr = [...arr];
console.log(newArr);
当有大量答案时,您必须使用最佳实践来回答此问题。
我建议您使用数组展开符(array spreads)来复制数组。
var arr1 = ['a','b','c'];
var arr2 = […arr1];
众所周知,在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是用来切割数组的一部分,它将切割数组的一部分而不影响原始数组,在slice中,如果没有指定数组的开始和结束,它将切割整个数组并基本上复制整个数组,因此我们可以轻松地说:
var arr2 = arr.slice(); // make a copy of the original array
3) 另外还有一种联系方法,用于合并两个数组,但我们只需要指定其中一个数组,然后就可以将其值复制到新的联系数组中:
var arr2 = arr.concat();
4) 同样的,字符串化和解析方法并不推荐使用,但可以是复制数组和对象的简单方式:
var arr2 = JSON.parse(JSON.stringify(arr));
5) Array.from方法,这个方法并不被广泛支持,在使用之前请检查不同浏览器的支持情况:
const arr2 = Array.from(arr);
6) 使用ECMA6的方法,也没有完全支持,但是如果你想要转换,babelJs可以帮助你:
const arr2 = [...arr];
var arr1 = ['a','b','c'];
var arr2 = [];
var arr2 = new Array(arr1);
arr2.push('d'); // Now, arr2 = [['a','b','c'],'d']
console.log('arr1:');
console.log(arr1);
console.log('arr2:');
console.log(arr2);
// Following did the trick:
var arr3 = [...arr1];
arr3.push('d'); // Now, arr3 = ['a','b','c','d'];
console.log('arr3:');
console.log(arr3);
arr1
和arr2
是存储在不同堆栈中的两个不同的数组变量。
在jsfiddle上查看。var arr2 = [arr1];
)。 - Timothy003document.write(arr2)
更改为console.log(arr2)
,以便展示嵌套数组结构并更好地说明@Timothy003的正确评论。不过,var arr3 = [...arr1]
就解决了问题。运行代码片段以查看结果。(document.write(arr2)
的输出有点误导人,所以我不怪你)。 - Jürgen Fink
slice
和splice
操作的性能表现很好,而新的扩展运算符和Array.from
的实现则比较慢。可参考perfjs.fnfo。 - Pencroffvar arr2 = arr1.splice();
进行深度复制,但是如果您的数组元素包含文字结构(即[]
或{}
)或原型对象(即function () {}
、new
等),则此技术将无法工作。请参见下面的答案以获取更多解决方案。 - tim-montaguelet arr2 = [...arr1];
。详见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator。 - Hinricha = b;
时,实际上是告诉程序在随机访问内存中指向同一个符号链接。当更改此符号链接处的值时,会影响到a
和b
... 因此,如果你使用扩展运算符a= [...b];
,程序将创建一个额外的符号链接到随机访问内存中的不同位置,然后你可以独立地操作a
和b
。 - 71GA