如何将所有项目从一个数组复制到另一个数组

How to copy all items from one array into another?

本文关键字:数组 一个 复制 另一个 项目      更新时间:2023-09-26

如何将数组的每个元素(其中元素是对象)复制到另一个数组中,使它们完全独立?

我不想改变一个数组中的元素而影响另一个数组

这里的关键是

  1. 数组中的条目是对象,
  2. 你不希望一个数组中对象的修改在另一个数组中出现。

这意味着我们不仅需要将对象复制到新数组(或目标数组),还需要创建对象的副本。

如果目标数组不存在…

…使用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

这也是爱彼迎的最佳实践。https://github.com/airbnb/javascript es6-array-spreads

注意: ES2015中的扩展语法在复制数组时会深入一级。因此,它们不适合复制多维数组。

var clonedArray = array.concat();

如果你想保持引用:

Array.prototype.push.apply(destinationArray, sourceArray);

有两点需要注意。

  1. 使用array.concat()不能使用Angular 1.4.4和jQuery 3.2.1(这是我的环境)。
  2. array.slice(0)是对象。所以如果你执行newArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0),两个新数组将只引用一个数组,改变一个会影响另一个。

或者,使用newArray1 = JSON.parse(JSON.stringify(old array))只会复制值,因此它每次都会创建一个新数组。

如果你正在使用nodeJS,我建议使用concat()。在所有其他情况下,我发现slice(0)工作良好。

structuredClone代表了一种执行深度克隆的新方法。

const objArray = [{name:'first'}, {name:'second'}, {name:'third'}, {name:'fourth'}];
// Clone it
const clonedArr = structuredClone(objArray);
console.log(clonedArr)