シャローコピーとディープコピー
JavaScript でオブジェクトや配列をコピーする際、シャローコピー(浅いコピー)とディープコピー(深いコピー)の違いを理解しておく必要があります。この違いを知らないと、意図せず元のデータを変更してしまうバグの原因になります。
参照の基本
JavaScript のオブジェクトと配列は参照型です。変数に代入しても、実際のデータへの「参照」がコピーされるだけで、データ自体は共有されます。
const original = { name: "田中" };
const reference = original;
reference.name = "山田";
console.log(original.name); // "山田"(元も変わってしまう)シャローコピーとは
シャローコピーは、オブジェクトの1階層目のプロパティだけをコピーします。ネストしたオブジェクトや配列は参照のままです。
const original = {
name: "田中",
address: { city: "東京" }
};
const shallow = { ...original };
shallow.name = "山田";
console.log(original.name); // "田中"(影響なし)
shallow.address.city = "大阪";
console.log(original.address.city); // "大阪"(影響を受ける!)1階層目のプロパティ
コピーされるため、変更しても元に影響しない
ネストしたオブジェクト
参照が共有されるため、変更が元にも反映される
シャローコピーの方法
シャローコピーを作る代表的な方法は以下の通りです。
const obj = { a: 1, b: 2 };
// スプレッド構文
const copy1 = { ...obj };
// Object.assign()
const copy2 = Object.assign({}, obj);
// 配列の場合
const arr = [1, 2, 3];
const arrCopy1 = [...arr];
const arrCopy2 = arr.slice();ディープコピーとは
ディープコピーは、ネストしたオブジェクトや配列も含めて完全に複製します。元のデータとの参照の共有は一切ありません。
const original = {
name: "田中",
address: { city: "東京" }
};
const deep = JSON.parse(JSON.stringify(original));
deep.address.city = "大阪";
console.log(original.address.city); // "東京"(影響なし)ディープコピーの方法
ディープコピーを作る主な方法を比較します。
JSON.parse(JSON.stringify())
最も簡単な方法ですが、関数、undefined、Date、Map、Set などは正しくコピーできません。
structuredClone()
モダンな方法で、Date や Map なども正しくコピーできます。ただし関数は含められません。
// structuredClone() を使う(推奨)
const original = {
date: new Date(),
items: [1, 2, 3]
};
const deep = structuredClone(original);
console.log(deep.date instanceof Date); // true用途に応じて適切なコピー方法を選択することが重要です。