【でぃーぷこぴー】

ディープコピー(深いコピー) とは?

最終更新:
💡 入れ子のデータも別にする「深いコピー」

オブジェクトや配列の内側にあるデータも複製し、コピー側の変更が元のデータに影響しないようにする方法。実際に複製できる型や情報は、使うコピー手段によって異なる。

📌 このページのポイント
浅いコピーと深いコピー:参照の違い シャローコピー ディープコピー 元 addr → コピー addr → 元 addr → コピー addr → 共有 city: 東京 元のaddr 東京 別のaddr 大阪 addr.cityを変えると 元にも影響する コピーのcityだけ変更 元のcityは東京のまま 使うコピー方法によって、対応する型が異なる
通常の入れ子オブジェクトの例。structuredCloneも関数やDOMノードなどは複製できません。
ひよこ ひよこ
いつディープコピーが必要になるの?
ペンギン先生 ペンギン先生
入れ子のデータをコピー側で変えても、元に影響させたくないときだよ。テスト用データや変更前の状態を保存する場面が例になるね。必要な部分だけを複製する方法もあるよ
ひよこ ひよこ
structuredCloneって何?
ペンギン先生 ペンギン先生
対応する型を深くコピーする関数だよ。Date・Map・Setや循環参照にも対応するんだ。ただし関数やDOMノードなどは複製できず、DataCloneErrorになるので、どんな値でも完全にコピーできるわけではないよ
ひよこ ひよこ
JSON.parse(JSON.stringify())じゃダメなの?
ペンギン先生 ペンギン先生
JSONで表せるデータには使えるけれど、Dateは文字列になるよ。関数やundefinedはオブジェクトのプロパティでは省略され、配列ではnullになるんだ。循環参照はエラーになるので、元と同じ型や構造を保つ方法とは限らないよ
ひよこ ひよこ
ReactやReduxの更新では毎回必要なの?
ペンギン先生 ペンギン先生
全体のディープコピーは必須ではないよ。変更する入れ子の経路だけ新しいオブジェクトにし、他の部分を共有する方法があるんだ。Redux ToolkitのImmerもこの考え方で、不要な全体コピーを避けられるよ
もっと詳しく知りたい人へ

structuredCloneでクラスの振る舞いまで複製できる?

通常のオブジェクトでは、プロトタイプやプロパティ記述子、getter/setterなどをそのまま複製するわけではありません。独自クラスの振る舞いまで含めた複製が必要なら、その型に合った方法を選んでください。関数やDOMノードも複製できないため、呼び出し前に対象の型を確認します。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「ディープコピー」って出てきたら「入れ子のデータも別にするコピー」と思えばだいたいOK!
📖 おまけ:英語の意味
「deep copy」 = 深いコピー
💬 deepは「深い」という意味で、入れ子になったデータの深い階層も複製するイメージだよ

参考資料

← 用語集にもどる