【しゃろーこぴー】

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

💡 表紙だけコピーして中身は同じ本を共有する「浅いコピー」
📌 このページのポイント
シャローコピー vs ディープコピー シャローコピー(浅いコピー) 元データ name: "太郎" addr: { ... } コピー name: "太郎" addr: → 同じ参照先! ネストされたオブジェクトは共有 ディープコピー(深いコピー) 元データ name: "太郎" addr: { ... } 独立したaddr コピー name: "太郎" addr: { ... } 独立したaddr すべて独立したコピー 浅い: 表面だけコピー、中身は共有 深い: 中身まで完全にコピー
シャローコピーのイメージ
ひよこ ひよこ

なんで普通にコピーするだけじゃダメなの?

ペンギン先生 ペンギン先生

JavaScriptオブジェクトを const b = a とすると、コピーではなく同じオブジェクトへの参照が複製されるだけ。bを変えるとaも変わってしまう。独立したコピーを作るにはスプレッド構文 {...a} などを明示的に使う必要がある。

ひよこ ひよこ

シャローコピーの罠ってどんなもの?

ペンギン先生 ペンギン先生

const original = { user: { name: "Ken" } } をシャローコピーして copy.user.name = "Tom" とすると、original.user.name も "Tom" になる。ネストされたオブジェクトは参照が共有されているから。これが浅いコピーの罠。

ひよこ ひよこ

Reactではどう気をつければいい?

ペンギン先生 ペンギン先生

Reactの状態更新では「新しいオブジェクト参照」を作る必要がある。一階層のオブジェクトなら setState({...state, key: newValue}) でOK。ネストが深い場合は該当の階層もスプレッドするか、immerライブラリを使うと安全。

ひよこ ひよこ

ディープコピーってどうやるの?

ペンギン先生 ペンギン先生

JavaScriptならstructuredClone(original)が一番簡単で安全な方法だよ。以前はJSON.parse(JSON.stringify(obj))という裏技が使われていたけど、関数やundefined、Dateオブジェクトが正しくコピーされない問題があった。structuredCloneはブラウザNode.js両方で使えて、これらの問題も解決しているんだ。

ひよこ ひよこ

配列のシャローコピーも同じ問題があるの?

ペンギン先生 ペンギン先生

あるよ。[...array]やArray.from(array)でコピーしても、中にオブジェクトが入っていれば参照が共有される。たとえばconst copy = [...users]としても、copy[0].name = 'Tom'とするとusers[0].nameも変わってしまう。配列の中身がプリミティブ値(数値や文字列)だけなら問題ないけど、オブジェクトを含む配列は要注意だよ。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
シャローコピーって出てきたら「一階層目だけコピーして中身のオブジェクトは共有する浅いコピー」と思えばだいたいOK!
📖 おまけ:英語の意味
「shallow copy」 = 浅いコピー
💬 shallow は「浅い」という意味で、データ構造の表面的な部分だけをコピーすることから
← 用語集にもどる