3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】JavaScriptのシャローコピーとディープコピーの違いについて

Last updated at Posted at 2025-05-05

はじめに

スプレッド構文を使ってオブジェクトをコピーした際に「シャローコピーとは何か」が分からず、挙動に戸惑ったため、調べた内容をまとめました。

この記事は個人的なアウトプットを目的として作成したものです。そのため、誤った情報や不足している内容が含まれている可能性があります。もし間違いや気になる点がございましたら、ぜひご指摘いただけますと幸いです

シャローコピー

MDNでは以下のように説明されています。

オブジェクトのシャローコピーとは、コピーがコピー元のオブジェクトとプロパティにおいて同じ参照を共有する(同じ基礎値を指す)コピーのことを指します。その結果、コピー元とコピー先のどちらかを変更すると、もう一方のオブジェクトも変更される可能性があります。そのため、意図せずにコピー元やコピー先に予期しない変更が発生してしまう可能性があります。この挙動は、ソースとコピーが完全に独立しているディープコピーの挙動とは対照的です。

つまり、コピー元とコピー先は参照を共有しているため、ネストされたプロパティなどを変更すると、もう一方にも影響が出ます。

シャローコピーで影響が出ないパターン(第1階層)

const object = { name: "soccer" };
const newObject = { ...object }; // {name: "soccer"}
newObject.name = "baseball"; // {name: "baseball"}

この場合、コピーしたのは第1階層のみで、nameはプリミティブ値のため参照共有ではありません。したがって元のobjectには影響がありません。

シャローコピーで影響が出るパターン(ネストあり)

  const object = {
    name: "soccer",
    like: {
      team: "yokohama",
    },
  };
  const newObject = { ...object };

  newObject.name = "baseball"; // ← 第1階層(影響なし)
  newObject.like.team = "losangeles"; // ← 第2階層(元にも影響する)

  console.log(object); // { name: "soccer", like: { team: "losangeles" } }
  console.log(newObject); // { name: "baseball", like: { team: "losangeles" } }

このように、第2階層のlike.teamが共有されていたため、片方を変更するともう一方も変わってしまいます。

ディープコピー

ディープコピーは、コピー元とコピー先が完全に独立した参照を持つコピーです。そのため、片方を変更してももう一方には影響しません。

MDNでは以下のように説明されています。

オブジェクトの ディープコピー とは、コピー先のオブジェクトのプロパティがコピー元のオブジェクトのプロパティと同一の参照(同じ値を指す)で共有しないコピー方法のことです。結果として、コピー元かコピー先のどちらかを変更しても、もう一方オブジェクトにも変更を及ぼしていないことを保証できます。すなわち、コピー元かコピー先に意図せずに予期しない変更が加えられるこはありません。この振る舞いはシャローコピーとは対照的です。シャローコピーでは、コピー元かコピー先のどちらかを変更するともう一方のオブジェクトも変更される可能性があります。

lodashを使ったディープコピー

ディープコピーの方法は複数ありますが、ここではlodashというライブラリのcloneDeepを使用した例を紹介します。

  const object = {
    name: "soccer",
    like: {
      team: "yokohama",
    },
  };
  
  const newObject = _.cloneDeep(object);
  newObject.name = "baseball";
  newObject.like.team = "losangeles";

  console.log(object); // { name: "soccer", like: { team: "yokohama" } }
  console.log(newObject); // { name: "baseball", like: { team: "losangeles" } }

このように、元のオブジェクトはまったく変更されていないことが確認できます。

終わりに

シャローコピーとディープコピーの違いを正しく理解することは、オブジェクトの操作で思わぬバグを防ぐ上で非常に重要だと感じました。2つの使い分けについてはまだしっかり理解できていないのでこれからこの2つについてさらに理解を深めていきたいです。

3
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?