如何将一个由对象构成的数组中的每个元素复制到另一个数组中,使它们完全独立?
我不想改变一个数组中的元素会影响另一个数组。
如何将一个由对象构成的数组中的每个元素复制到另一个数组中,使它们完全独立?
我不想改变一个数组中的元素会影响另一个数组。
关键点如下:
这意味着我们不仅需要将对象复制到新数组(或目标数组)中,还需要创建对象的副本。
...可以使用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
调用:
有时候人们真的想要一个“一行代码”的解决方案,即使没有特定的原因。如果你需要这样做,你可以创建一个新的数组,然后使用扩展符将其展开为单个push
调用:
destinationArray.push(...sourceArray.map(obj => copy(obj)));
push
方法: Array.prototype.push.apply(destinationArray, sourceArray);
- Veikko KarsikkodestinationArray.push(...sourceArray);
对我来说完美地运作了。 - Kishor Pawar使用以下方法可以轻松使其工作:
var cloneArray = JSON.parse(JSON.stringify(originalArray));
我在使用 arr.concat()
或 arr.splice(0)
时遇到问题,无法得到一个深度复制的数组。上面的代码片段可以完美地工作。
JSON.stringify
过程中,数组中的undefined
和任何函数都将被转换为null
,尽管这是克隆数组本身及其所有子元素的最简单方法,以便进一步的更改不会影响原始数组,因此如果上述警告对您的用例没有任何问题,它仍然非常有用。 - fredrivett使用数组字面量和展开语法是克隆数组的好方法,这得益于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 中的展开语法只能对数组进行一层深度的复制,因此不适用于多维数组的复制。
...
不是运算符。) - T.J. Crowderhttps://developer.mozilla.org/.../Operators/Spread_operator#Copy_an_array
。
无论如何,我已经更新了答案,改为使用扩展语法。 - MauricioLealvar clonedArray = array.concat();
有两个重要的注意事项。
array.concat()
不起作用。array.slice(0)
是一个对象。因此,如果您执行像 newArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0)
这样的操作,则两个新数组将引用同一个数组,更改其中一个将影响另一个。或者,使用 newArray1 = JSON.parse(JSON.stringify(old array))
只会复制值,因此每次都会创建一个新数组。
array.slice(0)
每次调用都会返回一个新对象,改变一个返回的实例并不会改变其他实例。如果您正在使用更改此行为的“框架”,那么这只是一个错误/糟糕的设计。 - wonder.micesecond
中,first
将不会有它。 - wonder.mice如果你在使用nodeJS,我建议使用concat()
。其他情况下,我发现slice(0)
效果也很好。
structuredClone
表示一种进行深层克隆的新方法。
const objArray = [{name:'first'}, {name:'second'}, {name:'third'}, {name:'fourth'}];
// Clone it
const clonedArr = structuredClone(objArray);
console.log(clonedArr)
a = [1, 2, 3], b = [4, 5, 6]
。如果你执行a = b.slice()
,你已经复制了b。你没有将b的值复制到a中。a的数组可能被多个地方引用。 - gman