【しゃろーこぴー】

シャローコピー(浅いコピー) とは?

最終更新:
💡 外側は別、内側のオブジェクトは一緒

コピー先の外側は新しく作り、そこから参照する内部のオブジェクトは共有するコピー方法。JavaScriptの通常のオブジェクトや配列で具体例を説明する。

📌 このページのポイント
浅いコピー:外側は別、参照先は共有originalcount:1userへの参照copycount:2userへの参照同じuserオブジェクトname:Ken → Tomuser.nameの変更は、両方から見える差し替えと、中の書き換えを分けよう
スプレッドで複製し、copy.countとcopy.user.nameを変更した例。外側と共有する参照先の違いを示す。
ひよこ ひよこ
同じデータを別の変数に入れれば、コピーになる?
ペンギン先生 ペンギン先生
JavaScriptのオブジェクトで const b = a とすると、aとbは同じオブジェクトを指すよ。通常のオブジェクトなら const copy = {...a} として、別の外側を作れる。これが浅いコピーの一例だね。
ひよこ ひよこ
外側は別なのに、中身は変わるの?
ペンギン先生 ペンギン先生
たとえば original = {count: 1, user: {name: "Ken"}} をスプレッドでコピーする。copy.count = 2 としても元のcountは1のまま。でも copy.user.name = "Tom" とすると、共有しているuserを変えるので元のnameもTomになるんだ。
ひよこ ひよこ
配列なら安心?
ペンギン先生 ペンギン先生
配列にも同じことがあるよ。[...users]やusers.slice()は別の配列を作るけれど、要素のオブジェクトは共有する。copy[0]を別の値に差し替えるのと、copy[0].nameを変更するのでは、影響が違うんだ。
ひよこ ひよこ
Reactの状態を変えるときは?
ペンギン先生 ペンギン先生
元の状態を直接書き換えず、変更する部分から外側まで新しく作るよ。たとえばuserのnameを変えるなら、userとそれを持つ外側の両方をコピーする。全部を深くコピーする必要はなく、Immerで更新の記述を短くする方法もあるよ。
ひよこ ひよこ
structuredCloneなら、何でも深くコピーできる?
ペンギン先生 ペンギン先生
対応する型なら深くコピーできるよ。Dateや循環参照を扱える一方、関数やDOMノードはDataCloneErrorになる。クラスの独自のプロトタイプもそのまま複製されるわけではない。扱う値と、独立させたい部分に合わせて方法を選ぶんだ。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「シャローコピー」って出てきたら「外側をコピーして、内部のオブジェクトは共有する浅いコピー」と思えばだいたいOK!
📖 おまけ:英語の意味
「shallow copy」 = 浅いコピー
💬 shallowは「浅い」。外側を複製しても、内部のオブジェクトへの参照までは独立させないコピーを表すよ。

参考資料

← 用語集にもどる