TypeScriptやJavaScriptのコードを書く際、オブジェクトのコピーをしたことはありますか?
その際、本当に思った通りの動作をしてくれましたか?
この記事ではオブジェクトの参照渡し、シャローコピー、ディープコピーについて紹介していきます!
TypeScriptを使ったプログラミングで避けては通れない「オブジェクトのコピー」について紹介します。
「参照渡し」「シャローコピー」「ディープコピー」とは何か
それぞれの違いと使いどころを具体的なコード例とともに解説します。
これらの知識を身につけることで、オブジェクトの扱いに悩むことが少なくなるでしょう!
まずは、オブジェクトの基本的な性質から学びましょう。
let obj1 = {name: "Hoge", age: 20};
let obj2 = obj1;
obj2.name = "Fuga";
console.log(obj1.name);
コード内では obj1.name
を出力していますが Fuga
が表示されてしまいます。
obj2
を変更しただけなのに、なぜ obj1
の内容まで変わるのでしょう?
これは obj2 = obj1;
の部分で obj1
の参照を obj2
にコピーしているからです。
そのため obj2
で行われた変更は obj1
にも反映されるのです。
これが 参照渡し と呼ばれるものです。
先程の参照渡しの挙動を避ける方法の一つが シャローコピー です。
let obj1 = {name: "Hoge", age: 20};
let obj2 = {...obj1};
obj2.name = "Fuga";
console.log(obj1.name);
上記のコードでは Hoge
が表示されるはずです。
これがシャローコピーの力です。
ここでは {...obj1}
を使って obj1
のプロパティを新しいオブジェクトにコピーしています。
そのため obj2
への変更が obj1
に影響を与えません。
ただし、この方法も万能ではありません。
オブジェクトがネストされている場合(オブジェクトの中にオブジェクトがある場合)には、この方法だけでは完全なコピーを作成することができないため注意が必要です。
ネストされたオブジェクトに対しても対応可能なコピー方法が、ディープコピーです。
let obj1 = {name: "Hoge", age: 20, address: {country: "Japan", city: "Tokyo"}};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj2.address.city = "Nagoya";
console.log(obj1.address.city);
上記のコードを実行すると Tokyo
が表示されます。
この方法によってネストされたオブジェクトに対しても完全なコピーが可能となります。
ここでは JSON.parse(JSON.stringify(obj1))
を利用して obj1
を一度 JSON 文字列に変換し、再びオブジェクトに戻すことでオブジェクト全体を新しいオブジェクトにコピーしています。
他にも Lodash を使用してディープコピーを行う方法などが存在します。
以上がTypeScriptでのオブジェクトのコピーに関する基本的な知識です。
覚えておくと便利なのでぜひご活用ください!
TypeScriptの短絡評価の使い方「&&」「||」「??」の解説
TypeScriptのタイマー関数setTimeoutとsetIntervalの使い方
TypeScriptの多次元配列の使い方についてわかりやすく解説
TypeScriptでのタプルの使い方と実践テクニックを解説
TypeScriptのimport typeをわかりやすく解説
TypeScriptの配列やオブジェクトのソート完全ガイド
TypeScriptコメントアウトの使い方 完全ガイド
TypeScriptのオブジェクトとプロパティの存在チェック完全ガイド
TypeScriptで即時関数を使う方法を解説!基本から実践的な使い方まで