JavaScriptでイミュータブルなオブジェクトを扱うためのライブラリとして、FacebookによるImmutable.jsがあります。

フロントエンド開発において、ReduxをはじめとするFluxアーキテクチャとあわせて、Modelドメインを扱う際にImmutable.jsを採用する事例なども増えつつあるようです。

今回は、このImmutable.jsについてまとめてみました。

イミュータブルとは

イミュータブル(Immutable)とは、ひとことで言うと値が変わらないことです。 この逆はミュータブル(Mutable)で、JavaScriptでのlet/constによる一般的な変数定義ではミュータブルとなります。

イミュータブルであることのメリットとして、宣言箇所を見ればその変数の状態が特定できるというものがあります。 なぜなら、その変数はそれ以降で不変だからです。

ミュータブルな変数を排除することで、バグが入る余地を減らすことができ、また理解しやすいコードになります。

注意すべき点として、constで定義したオブジェクトは一見イミュータブルですが、const再代入ができないという意味に過ぎません。 たとえば、以下のように、代入でなく追加・削除を行なった場合、オブジェクトは変わってしまいます。

const a = [1, 2];
a.push(3);
console.log(a); //=> [1, 2, 3]

こうなると、変数定義以降で状態が変わってしまい、コードベースが大きくなるほどこれを追うのが困難になります。

こうではなく、以下のように元のオブジェクトに変更が加わらない方が好ましいといえます(コードは動作イメージです)。

const a = [1, 2];
const b = a.push(3);
console.log(a); //=> [1, 2]
console.log(b); //=> [1, 2, 3]

Immutable.js

Immutable.jsは、上記のようなイミュータブルなオブジェクトを扱うためのライブラリです。 前述の例は、コレクションを扱うListAPIにより、以下のように書けます。

const a = Immutable.List([1, 2]);
const b = a.push(3);
console.log(a.toJS()); //=> [1, 2]
console.log(b.toJS()); //=> [1, 2, 3]

API

List以外にも、オブジェクトを扱うMap、クラスを生成するためのRecordなどがあり、JavaScriptで扱うおよその値をイミュータブルにできます。

詳しくは公式ドキュメントをご覧ください。

Fluxアーキテクチャへの導入

Reactの公式ドキュメントの中で、FluxアーキテクチャにおけるModelドメインとしてImmutable.jsを導入することを推奨しています。

Fluxアーキテクチャによりアプリケーションを開発している場合、ビジネスロジックがActionやStore、Componentなどに分散しがちですが、Modelというドメインを設けることでこれを集約できます。 Immutable.jsのRecordAPIを用いれば、これを簡単に実現できます。

これについての詳細は、別途記事にしたいと思います。

参考記事