【Angular】配列やオブジェクトのコピーの注意点 - ChuN6868/CodeChrysalis-fullstuck-project GitHub Wiki
🧠 配列コピーと参照の違いまとめ
✅ 比較対象
番号 |
コピー方法 |
内容 |
① |
同じ配列を共有している場合 |
arr1 = arr2 |
② |
スプレッド構文による浅いコピー |
arr2 = [...arr1] |
③ |
スプレッド+mapによる1階層の深いコピー |
arr2 = arr1.map(item => ({ ...item })) |
📋 各パターンの比較
項目 |
① 同じ配列を共有 |
② スプレッド構文(浅いコピー) |
③ map+スプレッド(1階層の深いコピー) |
配列自体は別になる? |
❌ いいえ |
✅ はい |
✅ はい |
中のオブジェクトも別? |
❌ いいえ |
❌ いいえ |
✅ はい |
片方を変更すると他方は? |
✅ 影響あり |
✅ 影響あり |
❌ 影響なし |
安全性 |
❌ 危険 |
⚠️ 注意 |
✅ 安全 |
主な用途 |
同期処理・テスト |
並び替え・一時処理など |
安全なコピーが必要なとき |
💡 実例コード
① 同じ配列を共有している場合
const shared = [{ name: 'Alice' }];
const arr1 = shared;
const arr2 = shared;
arr2[0].name = 'Bob';
console.log(arr1[0].name); // "Bob" ← arr1 も変わる
② スプレッド構文(浅いコピー)
const arr1 = [{ name: 'Alice' }];
const arr2 = [...arr1];
arr2[0].name = 'Bob';
console.log(arr1[0].name); // "Bob" ← 中のオブジェクトは共有されている
③ map+スプレッド構文(1階層ディープコピー)
const arr1 = [{ name: 'Alice' }];
const arr2 = arr1.map(item => ({ ...item }));
arr2[0].name = 'Bob';
console.log(arr1[0].name); // "Alice" ← 元のデータは変わらない
🧭 ネストが深い場合のコピー方法(参考)
✅ structuredClone()
(ブラウザ対応)
const deepCopy = structuredClone(arr1);
✅ lodash.cloneDeep()
(ライブラリ)
import cloneDeep from 'lodash/cloneDeep';
const deepCopy = cloneDeep(arr1);
🌍 他言語でも同じことが当てはまる?
✅ 同じ参照の問題が起こる代表的な言語
言語 |
内容・コメント |
✅ JavaScript |
TypeScript と同じ。配列・オブジェクトは参照型 |
✅ Python |
list , dict は参照型。copy() や deepcopy() が必要 |
✅ Java |
ArrayList , Map などは参照型。clone() や new コピーが必要 |
✅ C# |
class は参照型、List<T>.ToList() でコピーできる |
✅ Ruby |
Array , Hash は参照型。.dup , .clone でコピー |
✅ PHP |
配列はコピーされるが参照渡しも可能。clone でオブジェクト複製 |
✅ Swift |
class は参照型、struct は値型でコピーされる |
❌ 適用されにくい(ただし似た問題は起こる)
言語 |
コメント |
❌ C/C++ |
値型中心だが、ポインタを使えば同様の参照問題が起きる |
❌ Go |
配列は基本的に値渡し。slice や map で似た問題が発生することあり |
✅ まとめ:選び方の目安
目的 |
推奨コピー方法 |
同じデータをそのまま共有したい |
arr1 = arr2 |
配列構造だけコピーしたい(中身共有OK) |
arr2 = [...arr1] |
中のオブジェクトも完全に独立させたい |
arr2 = arr1.map(item => ({ ...item })) |
ネストされた構造も全部独立させたい |
structuredClone() または cloneDeep() |