bff

フルスタックエンジニアを目指して学んだことなどを記録しています

javascriptにおけるimmutableのメリット・デメリット

ReactのチュートリアルでImmutableについて触れていたため、javascriptにおけるImmutableのメリット・デメリットをまとめました。
 
 

最初に

Immutableとは、データを一度生成したらその後は値の変更を行わないことを指します。
値の変更を行いたい場合は、cloneを行い、その際に変更したい値のみを新しい値にします。
 

メリット

  • 履歴管理の実装が容易(例:Ctrl+zの元に戻す機能を実装する)
  • オブジェクトの変更検知が容易(shallow compare(浅い比較)で比較が完了する=全てのプロパティを比較する必要がない)
  • (Reactのみ)Reactによる再描画タイミングを決定しやすい・・・こちらは別途解説記事を記載します。
 
 

デメリット

  • cloneの生成や生成したデータのガーベッジコレクションのために、通常よりも多くCPUやメモリを消費する
  • javascriptでは言語サポートがないため、ライブラリの利用や実装の工夫が必要になる
 

Immutableの実現方法

  1. ライブラリの利用
    • immutable.jsBaobab.jsが利用できます。
    • immerは新しいライブラリですが、従来のJSのインターフェースが利用できて良さそうです。
    • いずれも学習コスト・セットアップが必要ですが、後述のstructural sharingを実現できるため、大規模なオブジェクトを利用するユースケースでは、ライブラリを導入した方がベターかと思います。
  2. 実装の工夫
    • Immutableにしたいオブジェクトをコピーし、一部のみ変更を加えるという実装が以下のSnippetの方法で可能です。
const obj = {
  prop1: “aaa”,
  updatedProp: “originalValue”,
  refProp: anotherObj // 適当なオブジェクトへの参照。ここでは{foo: “bar”}を指していると仮定。
}
 
const newObj = {
  ...obj, // スプレッド構文を使いobjのプロパティを展開します。
  updatedProp: “newValue”, // 更新したいプロパティのみ、更新後の値を定義します(ここではobj.updatedPropをnewValueに更新)
  newProp: “newProp” //  プロパティを追加したい場合は適宜加えます
};
  • updatedPropの挙動がわかりづらいので補足すると、obj.updatedPropがまず…objの展開で宣言されますが、その後のupdatedProp: “newValue”で上書きされます。
  • なお、スプレッド構文ではその時点のプロパティを展開するため、プロパティが値であればその値がコピーされ、参照であれば参照がコピーされます。
  • 例えば、obj.prop1の値を変更してもnewObj.prop1の値は変わりませんが、obj.anotherObj.fooを変更した場合、obj、newObjの双方の値が変更されます。
 

structural sharingとは

データ構造を保持しつつ、変更を加えるべき部分のみ、変更を行う方法です。
値の変更が行われていない部分については、オリジナルのデータを再利用することでメモリを節約します。
詳細は、こちらの記事が詳しいです。