在 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
相同的数组,而不是一个新的独立数组。如何将数组复制以获得两个独立的数组?快速示例:
var arr1 = ['a','b','c'];
// arr1 and arr2 are independent and primitive elements are stored in
// different places in the memory
var arr2 = arr1.slice();
arr2.push('d');
console.log(arr1); // [ 'a', 'b', 'c' ]
console.log(arr2); // [ 'a', 'b', 'c', 'd' ]
var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
// arr1 and arr2 are independent and reference's/addresses are stored in different
// places in the memory. But those reference's/addresses points to some common place
// in the memory.
var arr2 = arr1.slice();
arr2.pop(); // OK - don't affect arr1 bcos only the address in the arr2 is
// deleted not the data pointed by that address
arr2[0].x = 'z'; // not OK - affect arr1 bcos changes made in the common area
// pointed by the addresses in both arr1 and arr2
arr2[1][0] = 9; // not OK - same above reason
console.log(arr1); // [ { x: 'z', y: 'b' }, [ 9, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]
var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
arr2 = JSON.parse(JSON.stringify(arr1));
arr2.pop(); // OK - don't affect arr1
arr2[0].x = 'z'; // OK - don't affect arr1
arr2[1][0] = 9; // OK - don't affect arr1
console.log(arr1); // [ { x: 'a', y: 'b' }, [ 1, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]
const array = [1,2,3,4];
const arrayCopy1 = Object.values(array);
const arrayCopy2 = Object.assign([], array);
const arrayCopy3 = array.map(i => i);
const arrayCopy4 = Array.of(...array );
structuredClone
是一种新的深度克隆方式。
structuredClone(value)
structuredClone(value, { transfer })
transfer
是一个包含了需要移动而不是复制到返回对象中的可传递对象的数组。
你可能会发现它的算法非常有趣。
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
*/
toSource
不是标准的,在Chrome中无法工作。 - dmi3y// If a is array:
// then call cpArr(a) for each e;
// else return a
const cpArr = a => Array.isArray(a) && a.map(e => cpArr(e)) || a;
let src = [[1,2,3], [4, ["five", "six", 7], true], 8, 9, false];
let dst = cpArr(src);
只是写着:
arr2 = arr1.concat();
arr2 = [...arr1];
arr2 = arr1.map(x => Object.assign({}, x));
。Array.from
会改变数据,不提供深度复制/深度克隆。 - Sudhansu Choudhary对我来说,这些选项都不起作用,因为我正在处理一个深度嵌套对象的数组。对于ES6,我发现这个解决方案很有帮助。
const old_array = [{name:"Nick", stats:{age:25,height:2}},{name:"June", stats:{age:20,height:2}}];
const new_array = old_array.map(e => {
if (e.name === 'June') {
e = { ...e };
e.stats = {...e.stats, age: 22};
}
return e;
});
只有 new_array 会受到影响。
经过深入研究,我发现一个干净的方法是:
const arr1 = [['item 1-1', 'item 1-2'], ['item 2-1', 'item 2-2'], ['item 3-1', 'item 3-2']];
/**
* Using Spread operator, it will create a new array with no reference to the first level.
*
* Since, the items are not primitive, they get their own references. It means that any change on them,
* it will be still reflected on the original object (aka arr1).
*/
const arr2 = [...arr1];
/**
* Using Array.prototype.map() in conjunction Array.prototype.slice() will ensure:
* - The first level is not a reference to the original array.
* - In the second level, the items are forced (via slice()) to be created as new ones, so there is not reference to the original items
*/
const arr3 = arr1.map(item => item.slice());
你需要理解你想要操作的数组的复杂性,然后应用最佳解决方案(即在引用数组内引用项目)
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