不変なオブジェクトを扱う immutable.js を使ってみます。最近流行りの React とも相性がいいはずです。
インストール
npm
でインストールできます。例を ES6 で書くために babel
もインストールしておきます。
$ npm install -g babel
$ npm install immutable
例のコードは babel-node
で実行していきます。
List
immutable.js で Array
にあたるオブジェクトが List
になります。
Array
と同じように push
と pop
で要素の追加と削除ができます。少し違うのが返り値が新しい List
だということです。
import { List } from 'immutable';
const list1 = List([1, 2, 3]);
const list2 = list1.push(4);
const list3 = list1.pop();
console.log(list1); // List [ 1, 2, 3 ]
console.log(list2); // List [ 1, 2, 3, 4 ]
console.log(list3); // List [ 1, 2 ]
このように list1
の push
や pop
を呼び出しても list1
自身は変更されず、新しいオブジェクトが作られます。 shift
や unshift
も同様です。
オブジェクトが不変だと他の場所でオブジェクトが変更されている可能性がないので、プログラムで考慮する必要のある状態が減り、結果的にバグなども減らせます。
map
filter
reduce
などの動きは、ほとんどそのままなので大丈夫だと思います。 push
などは Array
とは動きが違ってしまうので、なれないと使いづらいかもしれません。
Map
{}
や ES6 の Map
に対応するのは Map
です。
ES6 の Map
と同じように get
set
で値の取得と設定ができます。
import { Map } from 'immutable';
const map1 = Map({ a: 1 });
const map2 = Map([['b', 2]]);
const map3 = map1.set('c', 3);
console.log(map1); // Map { "a": 1 }
console.log(map2); // Map { "b": 2 }
console.log(map3); // Map { "a": 1, "c": 3 }
List
と同じように set
が返すのは新しい Map
です。
map
filter
reduce
など他のメソッドも使えます。
map1
の a
だけ変更したい場合は map1.update('a', (x) => x * 2)
などとすれば a
が変更された新しい Map
が作られます。
React と組み合わせて
React と組み合わせて ToDo リストみたいなものを作ってみます。
import { List, Map } from 'immutable';
import * as React from 'react';
var App = React.createClass({
getInitialState() {
return {
tasks: List([
Map({ id: '1', done: false, name: '牛乳を買う' }),
Map({ id: '2', done: false, name: 'はがきを出す' })
])
};
},
render() {
return (
<ul>
{ this.state.tasks.map(task =>
<li key={ task.get('id') }>
<label>
<input type="checkbox" checked={ task.get('done') }
onChange={ this.toggleDone.bind(this, task.get('id')) } />
<span>{ task.get('name') }</span>
</label>
</li>
) }
</ul>
);
},
toggleDone(id) {
this.setState({
tasks: this.state.tasks.update(this.state.tasks.findIndex(t => t.get('id') === id),
t => t.update('done', d => !d))
});
}
});
React.render(<App />, document.body);
タスク一覧を表示するだけのプログラムです。
setState
の部分では update
などのメソッドを駆使してタスクのフラグを切り替えています。操作に対応するメソッドが提供されているので、それを使って state
を組み立てることができます。
まとめ
- immutable.js は不変なオブジェクトを提供する
- 不変なオブジェクトはバグを防ぐかもしれない
- React とも組み合わせて使える