# structuredCloneを使うついでディープコピーとシャローコピーを正しく理解する
Table of Contents
最近新しいプロジェクトでstructuredCloneを使った。
※それまではプロジェクトに入っていたlodash/cloneDeepを使っていた。
ついでに理解の浅いディープコピーとシャローコピーについて調べてみた。
シャローコピー
そもそもの理解だと、
const original = {a: 10, b:10, c:10}let copy = originalcopy.a = 100copy.b = 100copy.c = 100console.log(original)// [LOG]: {// "a": 100,// "b": 100,// "c": 100// }このコードを実行するとcopyを変更しているのにoriginalが変わっちゃっているというのがシャローコピーだと思っていた。
なのでずっとシャドーコピーのほうがしっくりくる気がするけどって思っていたけど、これはそもそもシャローコピーですらなく「参照共有」あるいは「参照代入」っていう名前らしい。
それじゃ、シャローコピーとは言うと
const original = { a: 10, b: 10, c: 10 };const copy = { ...original };copy.a = 100copy.b = 100copy.c = 100console.log(original)// [LOG]: {// "a": 10,// "b": 10,// "c": 10// }これのことらしい。
これだけ見ると何が問題なのかわからないけど、シャローコピーとは
新しいオブジェクトを作るが、中に入っているオブジェクトまではコピーしないこと
ということで、このコードだと何にも問題にならない。
例えば、下記のコードがシャローコピーらしい。
const original = { child : { description: "これはシャローコピー"} };const copy = { ...original };console.log(copy)// [LOG]: {// "child": {// "description": "これはシャローコピー"// }// }ただlogを見る限りcopy.childもコピーされている。
が、これはただコピーされているわけではなく、「参照共有」あるいは「参照代入」が行われているらしい。
そのため下記コードを実行すると、
const original = { note:"ここはコピーできている", child : { description: "これはシャローコピー"} };const copy = { ...original };copy.note = "これは変更できない"copy.child.description = "シャローコピーなので値が変更できる"console.log(original)// [LOG]: {// "note": "ここはコピーできている",// "child": {// "description": "シャローコピーなので値が変更できる"// }// }original内のobjectは変更できてしまう。
これにより、気が付かないうちに参照元を変更してしまったり、フレームワークが変更を検知しないといった問題が発生することがある。
これがシャローコピー。
ディープコピー
対してディープコピーとは、
オブジェクトの中にあるオブジェクトも含めて、すべて再帰的にコピーすること
とのこと。
const original = { note:"コピー", child : { description: "コピー"} };const copy = structuredClone(original);copy.note = "変更したい"copy.child.description = "変更したい"console.log(original)// [LOG]: {// "note": "コピー",// "child": {// "description": "コピー"// }// }再帰的にコピーしているので予期せぬ変更が起きない。
それなら何でもかんでもディープコピーしておけばいいのではと思うけど、
大きなデータをディープコピーするには時間もメモリも余計に使うというデメリットがあるというのは意識したほうがいいかもしれない。