今更 Underscore.js を使い出す

Underscore.js は、割りと古くからあるjsライブラリである。単体でも使えるし、backbone.js などが依存している事で知られている。筆者は普段、C#を使うが、LINQによって強力なコレクション処理が出来る。LINQに慣れると、LINQ無しでコレクション処理を行うのが大変辛い、中毒症状に陥るのだ。Underscore.js を使うと、コレクション処理によく使うものが関数化されているし、extendやらtemplateなどベンリ関数も用意される。jsでちょっと複雑なコレクション処理を書く必要が出てきたので、使ってみた。(ただし、LINQと使い勝手の比較はしてはいけない。VisualStudioとの組み合わせによる入力補完や、遅延実行は本当にパワフルだ)

Underscore.js
http://underscorejs.org/

リファレンス
http://underscorejs.org/#every

もし手軽に試したいなら、Underscore.jsのサイトでJavascriptコンソールを開けばいい。(Google Chromeの場合 F12キー→Escキー) すぐに _ オブジェクトにアクセスできる。

よく使いそうなもの

map,reduce さえ使えれば、あとはどうにでもなる気がする。

//ユーザー情報を用意する
var users = [  
 { id: 1, name: "aaa", level: 5, items:[1,2,3] }, 
 { id: 2, name: "bbb", level: 5, items:[3] }, 
 { id: 3, name: "ccc", level: 2, items:[2,2,2,2] }];

//mapを使ってidを抽出
var ids = _.map(users, function(u){ return u.id; })  
>[1, 2, 3]```

ラッパーを生成してオブジェクト指向っぽく書くほうが見通しが良くて好きだ。多少、メソッドチェーンもできる。(出来ない時もある)

_(users).sortBy(function(u) { return u.level; }).map(function(u){ return u.id; })

[3, 1, 2]```

条件に合う最初の要素はこのように取得できる

var id1user = _(users).find(function(u) { return u.id == 1 });

だがこの処理は、実行する度に走査するので、できる事ならインデックスをキャッシュしたい。

var userIndexById = _(users).reduce(function(memo, u) { memo[u.id] = u; return memo; }, {})

としたいところだが、これはあらかじめ用意されている関数を使えば一発で解決する

var userIndexById = _(users).indexBy(function(u) { return u.id; })  
>Object {1: Object, 2: Object, 3: Object}```

グルーピングもできる。

var usersByLevel = _(users).groupBy(function(u) { return u.level; })

Object {2: Array[1], 5: Array[2]}```

用意されている機能をすべて覚える必要は無いだろう。リファレンスを流し読みしながら使っていて、数個しか記憶していないし、それで十分だと思う。
リファレンスとは別に、ここが大変参考になった。
http://underscorejs.org/docs/underscore.html
ライブラリ内部のソースコードが載っているだけでなく、ちょっとしたTIPSや、なぜこうなっているのか?の説明まで載っており大変ベンリだった。