【超解説】JavaScriptでオブジェクトの配列を安全にコピーする方法:浅いコピー、深いコピー、ライブラリ
JavaScript でオブジェクトの配列を複製する方法
浅いコピー とは、元の配列の参照を新しい配列にコピーするだけです。つまり、新しい配列内のオブジェクトは、元の配列と同じオブジェクトを参照します。オブジェクトを変更すると、元の配列と新しい配列の両方に影響します。
深いコピー とは、元の配列の各オブジェクトのコピーを作成し、新しい配列に格納します。つまり、新しい配列内のオブジェクトは、元の配列とは別のオブジェクトになります。オブジェクトを変更しても、元の配列には影響しません。
浅いコピーの方法
スプレッド構文を使用する
これは、浅いコピーを作成する最も簡単で、最も現代的な方法です。
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const shallowCopy = [...originalArray];
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
slice()
メソッドは、配列の一部または全体を新しい配列として取り出すために使用できます。
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const shallowCopy = originalArray.slice();
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
for
ループを使用して、元の配列の各要素を新しい配列にコピーすることができます。
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const shallowCopy = [];
for (let i = 0; i < originalArray.length; i++) {
shallowCopy.push(originalArray[i]);
}
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
深いコピーの方法
JSON.stringify() と JSON.parse() を使用する
この方法は、オブジェクトを JSON 文字列に変換してから、その文字列を解析して新しいオブジェクトを作成することで、深いコピーを作成します。
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const deepCopy = JSON.parse(JSON.stringify(originalArray));
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(deepCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a:
JavaScript でオブジェクトの配列を複製する方法:サンプルコード
浅いコピー
スプレッド構文を使用する
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const shallowCopy = [...originalArray];
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
slice() メソッドを使用する
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const shallowCopy = originalArray.slice();
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
for ループを使用する
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const shallowCopy = [];
for (let i = 0; i < originalArray.length; i++) {
shallowCopy.push(originalArray[i]);
}
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(shallowCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
深いコピー
JSON.stringify() と JSON.parse() を使用する
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const deepCopy = JSON.parse(JSON.stringify(originalArray));
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(deepCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(deepCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
ライブラリを使用する
lodash
や underscore
などのライブラリには、深いコピーを作成するためのユーティリティ関数が含まれています。
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const deepCopy = _.cloneDeep(originalArray); // lodashを使用する場合
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(deepCopy); // [{ a: 1,
JavaScript でオブジェクトの配列を複製する方法:その他の方法
ネイティブの structuredClone() 関数を使用する (ES2020 以降)
ES2020 では、structuredClone()
関数が導入されました。これは、オブジェクトの深いコピーを作成するためのネイティブな方法です。
const originalArray = [{ a: 1, b: 2 }, { c: 3, d: 4 }];
const deepCopy = structuredClone(originalArray);
console.log(originalArray); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
console.log(deepCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
originalArray[0].a = 10;
console.log(originalArray); // [{ a: 10, b: 2 }, { c: 3, d: 4 }]
console.log(deepCopy); // [{ a: 1, b: 2 }, { c: 3, d: 4 }]
注意: structuredClone()
はまだ新しい機能であり、すべてのブラウザでサポートされているわけではありません。
手動で再帰的にコピーする
複雑なオブジェクト構造を持つオブジェクトの配列を複製する必要がある場合は、手動で再帰的にコピーする方が効率的な場合があります。
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj; // プリミティブな値の場合はそのまま返す
}
const copy = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const originalArray = [{ a: 1, b: { c: 5, d: 6 } }, { e: 7, f: 8 }];
const deepCopy = deepCopy(originalArray);
console.log(originalArray); // [{ a: 1, b: { c: 5, d: 6 } }, { e: 7, f: 8 }]
console.log(deepCopy); // [{ a: 1, b: { c: 5, d: 6 } }, { e: 7, f: 8 }]
originalArray[0].a = 10;
originalArray[0].b.c = 20;
console.log(originalArray); // [{ a: 10, b: { c: 20, d: 6 } }, { e: 7, f: 8 }]
console.log(deepCopy); // [{ a: 1, b: { c: 5, d: 6 } }, { e: 7, f: 8 }]
この方法は、可読性とメンテナンス性に優れていますが、複雑なオブジェクト構造を持つ場合や、パフォーマンスが重要な場合は推奨されません。
適切な方法を選択する
オブジェクトの配列を複製する方法を選択する際には、以下の要素を考慮する必要があります。
- 必要なコピーの深さ: 浅いコピーで十分なのか、深いコピーが必要なのか
- パフォーマンス: パフォーマンスが重要な場合は、
structuredClone()
関数を使用するか、ネイティブの JavaScript メソッド (例:slice()
) を使用する方が効率的な場合があります。
javascript