2022年9月13日JavaScriptツイートシェアはてブ送るPocketJavaScriptのイミュータブル(immutable)やミュータブル(mutable)の意味、ReactのState更新で重要なイミュータビリティ(immutability)について紹介します。データの更新方法についてデータの更新方法には『データの参照先の値を上書きする方法』と『データの参照先を変更して値を置き換える方法』の2つがあります。書き換えを意味するmutate(ミューテート)という英単語を用いて、前者は『ミューテートを伴うデータ更新』、後者は『ミューテートを伴わないデータ更新』と呼ばれています。1ミューテートを伴うデータ更新の例は以下の通りです。}ミューテートを伴わないデータ更新の例は以下の通りです。}イミュータブルとミュータブルについてイミュータブル(immutable)なデータとは『一度作成したら値を変更できない』性質、ミュータブル(mutable)なデータとは『一度作成した後も値が変更できる』性質を持つデータです。プリミティブ型はイミュータブルJavaScriptのプリミティブ型は以下の通りです。プリミティブ型は以下の通りです。1を実行するとnumは3から4にかわるため「プリミティブ型はミュータブルではないのか?」と思うかもしれません。numの値が変わったのはnumの参照先の値が変更されたからではなく、numの参照先が数値『3』から数値『4』に変更されたためです。参照先の値は上書きできないため、プリミティブ型はイミュータブルです。オブジェクト型はミュータブルJavaScriptのオブジェクトの例は以下の通りです。Dateオブジェクト型の値を直接変更した場合は『ミューテートを伴う更新』、データをコピーして参照先を変更してから値を更新した場合は『ミューテートを伴わない更新』となります。イミュータビリティについてイミュータビリティ(immutability、不変性)とは参照先のデータが不変であることを意味します。プリミティブ型はイミュータブルな性質を持つため、プリミティブ型のデータ更新ではイミュータビリティが保証されています。オブジェクトはミュータブルな性質を持つため、オブジェクトのデータ更新ではイミュータビリティが保証されていません。React・ReduxのStateの更新はミューテートを伴わない方法で行うReact・ReduxのStateの更新はミューテートを伴わない方法、つまり参照先の値を上書きしないイミュータビリティを保証した方法が推奨されています。ReactのState更新でミューテートをしないメリットは以下の通りです。1ミューテートを伴わないState更新のメリット複雑な機能が簡単に実装できるStateの更新を検出できるReactの再レンダーが正常に機能するState更新の正しい方法と誤った方法の具体例React・ReduxのState更新は、イミュータビリティが保証されている状態、つまり参照先の値を上書きするのではなく、参照先を変更してから値を変更するのが正しい方法です。以下ではケースに分けてStateの正しい更新方法と誤った更新方法の具体例を紹介します。今回紹介するケースは以下の通りです。誤った方法オブジェクトの場合は直接プロパティの値を更新するとイミュータビリティが保証されません。}正しい方法Object.assignやスプレッド演算子を利用してStateを浅いコピーし、コピーしたStateの値を更新します。浅いコピーの詳細解説はJavaScriptの浅い比較・浅い(深い)コピーの挙動まとめで紹介しています。Object.assignを利用した場合は以下のようになります。})スプレッド演算子を利用した場合は以下のようになります。誤った方法ネスト構造を持つオブジェクトを浅いコピーした場合、オブジェクト型のプロパティは参照先がコピーされます。浅いコピーを利用しているにもかかわらずミューテートを伴う更新となってしまいます。深いコピーを利用するlodashやJSON.parse(JSON.stringify(object))を利用した深いコピーを利用します。深いコピーの詳細解説はJavaScriptの浅い比較・浅い(深い)コピーの挙動まとめで紹介しています。階層ごとにスプレッド演算子を用意してコピーするオブジェクトの階層ごとにスプレッド演算子を利用した浅いコピーをすることで、参照先ではなく値がコピーできます。誤った方法Array.prototype.push()は配列を上書きするため、Stateの更新で使用する際は注意が必要です。ミューテートを伴わないメソッドで配列の追加を行うStateの更新で配列を追加する際はpush()の代わりにArray.prototype.concat()を利用するとよいです。array)やスプレッド演算子、Array.from()、Array.prototype.slice()を利用して配列の浅いコピーをしてから配列の更新をします。Object.assignを利用した例は以下の通りです。newMembers}スプレッド演算子を利用した例は以下の通りです。newMembers}Array.from()を利用した例は以下の通りです。newMembers}Array.prototype.slice()を利用した例は以下の通りです。newMembers}さいごにTwitter(@nishina555)やってます。↩RECOMMENDJavaScriptReactツイートシェアはてブ送るPocketプロフィールnishina大企業、ベンチャーと色々なところでWebエンジニアやっています。退職手続きから案件参画まで。人気の記事iPhoneの連絡先の保存がうまくできない!?原因は同期設定かも。