underscore.jsで気になる関数(Functions、Objects、Utility、Chaining編)

前回の続きです。今日はUnderscore.jsのFunctions、Objectsを中心に見ていきます。

Functions

FPぽいことするのに便利な関数が揃ってます。

_.memoize(function, [hashFunction])

メモ化関数です。関数の計算結果を記憶しておいて、再計算のコストを低くしてくれます。フィボナッチ数列を計算するのに便利そうです。

var fibonacci = _.memoize(function(n) {
  return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});

_.once(function)

関数を一度しか計算しない。初期化処理とかに便利そうです。

var initialize = _.once(createApplication);
initialize();
initialize();
// Application is only created once.

_.after(count, function)

count回関数が呼び出されて初めて、関数が実行されます。非同期の処理実行後に処理を行いたいときに便利そうです。

var renderNotes = _.after(notes.length, render);
_.each(notes, function(note) {
  note.asyncSave({success: renderNotes});
});
// renderNotes is run once, after all notes have saved.

_.wrap(function, wrapper)

関数の前後に処理を行えます。pythonのdecoratorぽいことができそう?

var hello = function(name) { return "hello: " + name; };
hello = _.wrap(hello, function(func) {
  return "before, " + func("moe") + ", after";
});
hello();
=> 'before, hello: moe, after'

_.compose(*functions)

関数合成をしてくれる関数です。かっこたくさん書かなくていいのは、楽です。

var greet    = function(name){ return "hi: " + name; };
var exclaim  = function(statement){ return statement.toUpperCase() + "!"; };
var welcome = _.compose(greet, exclaim);
welcome('moe');
=> 'hi: MOE!'

Objects

_.omit(object, *keys)

keysに指定したプロパティを除外してくれます。chainで使うと便利です。

_.omit({name: 'moe', age: 50, userid: 'moe1'}, 'userid');
=> {name: 'moe', age: 50}

_.defaults(object, *defaults)

デフォルトのプロパティを設定してくれます。

var iceCream = {flavor: "chocolate"};
_.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});
=> {flavor: "chocolate", sprinkles: "lots"}

_.tap(object, interceptor)

_chainといっしょに使うと便利です。計算途中の確認に使えます。

_.chain([1,2,3,200])
  .filter(function(num) { return num % 2 == 0; })
  .tap(alert)
  .map(function(num) { return num * num })
  .value();
=> // [2, 200] (alerted)
=> [4, 40000]

Utility

_.result(object, property)

objectのpropertyが関数なら結果を返して、値ならその値を返してくれます。

var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
_.result(object, 'cheese');
=> "crumpets"
_.result(object, 'stuff');
=> "nonsense"

Chaining

underscore関数がメソッドチェーンできるので便利です。

var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
var youngest = _.chain(stooges)
  .sortBy(function(stooge){ return stooge.age; })
  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
  .first()
  .value();
=> "moe is 21"

まとめ

2回にわたって、javascriptのユーティリティライブラリであるunderscore.jsのおもしろそうな関数の紹介を行いました。 underscore.jsは、ファイルサイズが小さく(minify&gzipで4.9kb)、実績も豊富(bakcbone.jsの依存ライブラリなのでHulu、foursquareなど)、ドキュメントもわかりやすく、おすすめです。