如何将数组的每个元素(其中元素是对象)复制到另一个数组中,以使它们完全独立?我不想改变一个数组中的元素来影响另一个。
7 回答
这里的关键是
- 数组中的条目是对象,并且
- 您不希望对一个数组中的对象的修改显示在另一个数组中。
这意味着我们不仅需要将对象复制到新数组(或目标数组),还需要创建对象的副本。
如果目标数组还不存在...
...用于map
创建一个新数组,并随时复制对象:
const newArray = sourceArray.map(obj => /*...create and return copy of `obj`...*/);
...复制操作是您喜欢复制对象的任何方式,根据用例,项目之间的差异很大。此问题的答案中深入讨论了该主题。但是例如,如果您只想复制对象而不是其属性引用的任何对象,则可以使用扩展符号(ES2015+):
const newArray = sourceArray.map(obj => ({...obj}));
这对每个对象(和数组)进行了浅拷贝。同样,对于深拷贝,请参阅上面链接的问题的答案。
这是一个使用不尝试处理边缘情况的简单形式的深拷贝的示例,请参阅边缘情况的链接问题:
function naiveDeepCopy(obj) {
const newObj = {};
for (const key of Object.getOwnPropertyNames(obj)) {
const value = obj[key];
if (value && typeof value === "object") {
newObj[key] = {...value};
} else {
newObj[key] = value;
}
}
return newObj;
}
const sourceArray = [
{
name: "joe",
address: {
line1: "1 Manor Road",
line2: "Somewhere",
city: "St Louis",
state: "Missouri",
country: "USA",
},
},
{
name: "mohammed",
address: {
line1: "1 Kings Road",
city: "London",
country: "UK",
},
},
{
name: "shu-yo",
},
];
const newArray = sourceArray.map(naiveDeepCopy);
// Modify the first one and its sub-object
newArray[0].name = newArray[0].name.toLocaleUpperCase();
newArray[0].address.country = "United States of America";
console.log("Original:", sourceArray);
console.log("Copy:", newArray);
.as-console-wrapper {
max-height: 100% !important;
}
如果目标数组存在...
...并且您想将源数组的内容附加到它,您可以使用push
一个循环:
for (const obj of sourceArray) {
destinationArray.push(copy(obj));
}
有时人们真的想要“一个班轮”,即使没有特别的理由。如果您引用它,您可以创建一个新数组,然后使用扩展符号将其扩展为单个push
调用:
destinationArray.push(...sourceArray.map(obj => copy(obj)));
让这个工作的简单方法是使用:
var cloneArray = JSON.parse(JSON.stringify(originalArray));
我在获取arr.concat()
或arr.splice(0)
提供深层副本时遇到问题。上面的片段完美地工作。
克隆数组的一个好方法是使用数组字面量和扩展语法。ES2015使这成为可能。
const objArray = [{name:'first'}, {name:'second'}, {name:'third'}, {name:'fourth'}];
const clonedArr = [...objArray];
console.log(clonedArr) // [Object, Object, Object, Object]
您可以在 MDN 的文档中找到此复制选项:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Copy_an_array
这也是Airbnb 的最佳实践。https://github.com/airbnb/javascript#es6-array-spreads
注意:ES2015 中的扩展语法在复制数组时会加深一层。因此,它们不适合复制多维数组。
var clonedArray = array.concat();
如果您想保留参考:
Array.prototype.push.apply(destinationArray, sourceArray);
有两个重要的注意事项。
- 使用
array.concat()
Angular 1.4.4 和 jQuery 3.2.1 (这是我的环境)不起作用。 - 是
array.slice(0)
一个对象。因此,如果您执行类似newArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0)
的操作,两个新数组将仅引用 1 个数组,而更改一个数组将影响另一个数组。
或者, usingnewArray1 = JSON.parse(JSON.stringify(old array))
只会复制该值,因此每次都会创建一个新数组。
concat()
如果您使用的是 nodeJS,我建议使用。在所有其他情况下,我发现slice(0)
效果很好。