配列のすべての要素 (要素がオブジェクトである場合) を別の配列にコピーして、完全に独立させるにはどうすればよいですか? ある配列の要素を変更して、他の要素に影響を与えたくありません。
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 clonedArray = array.concat();
concat()
nodeJS を使用している場合は、使用することをお勧めします。他のすべてのケースでは、問題なく動作することがわかりましたslice(0)
。