Underscore.jsの入り口

第3回 underscore.jsの関数とユーティリティとChaining

この記事を読むのに必要な時間:およそ 8 分

Chainingの機能

Chainingの機能をご紹介します。Chainingは,Underscore.jsの関数を連続して呼び出す方法です。コードを単純化することができます。

_.chain()

書式
_.chain(object)

objectをラップしたオブジェクトを返し,オブジェクトのメソッドを返します。ラップされたオブジェクトはUnderscore.jsの関数とArray prototypeのメソッド(reverse , push等)持っています。

var members = [
  { 'name': 'chiba', 'age': 25 },
  { 'name': 'kuhara', 'age': 24 },
  { 'name': 'abe', 'age': 26 },
  { 'name': 'ueno', 'age': 27 }
];

//一番若いメンバーを抽出します。
var youngmember = _.chain(members)
    .sortBy('age')
    .map(function(member) { return member.name + ':' + member.age; })
    .first()
    .value(); //ラップしたオブジェクトの値を返します。

youngmember;   
//=>  kuhara:24


//_.tap を使う事でChainingの途中の値の確認が行えます。
_.chain(members)
    .sortBy('age')
    .map(function(member) { return member.name + ':' + member.age; })
    
    // "kuhara:24,chiba:25,abe:26,ueno:27"がalertされます。
    .tap(alert) 
    .first()
    .value();

各種機能のご紹介

今回取り上げきれなかった各種機能を表にまとめて紹介します。

 コレクションの機能

メソッド名説明Alias
_.each(list, iterator, [context])listの各要素に対してiteratorを実行します。iteratorの引数は(element, index, list)になります。ネイティブの機能でforEach()が使える環境ではそちらを使います。forEach
_.map(list, iterator, [context])listの各要素に対してiteratorを実行した新しい配列を返します。iteratorの引数は(element, index, list)になります。ネイティブの機能でmap()が使える環境ではそちらを使います。collect
_.reduce(list, iterator, memo, [context])listの各要素に対してiteratorを実行し累積結果を返します。iteratorの戻り値は累積結果であり,次の要素に対してiteratorの呼び出しで引数として渡されます。iteratorの引数は(memo, value)になります。ネイティブの機能でreduce()が使える環境ではそちらを使います。inject, foldl
_.reduceRight(list, iterator, memo, [context])_.reduce()と同等の処理をlistの最後から実行します。ネイティブの機能でreduceRight()が使える環境ではそちらを使います。foldr
_.find(list, iterator, [context])listの各要素に対してiteratorを実行し,戻り値が最初に真になる値を返します。detect
_.filter(list, iterator, [context])listの各要素に対してiteratorを実行し,戻り値が真になる値を抜き出した配列を返します。ネイティブの機能でfilter()が使える環境ではそちらを使います。
_.where(list, properties)listの各要素に対してiteratorを実行し,properties(オブジェクトのkeyとvalue)と合致するものを抜き出した配列を返します。
_.findWhere(list, properties)listの各要素に対してiteratorを実行し,properties(オブジェクトのkeyとvalue)と最初に合致するものを返します。
_.reject(list, iterator, [context])listの各要素に対してiteratorを実行し,戻り値が偽になる値を抜き出した配列を返します。
_.every(list, [iterator], [context])listの各要素に対してiteratorを実行し,戻り値が全て真なら真を,1つでも偽なら偽を返します。ネイティブの機能でevery()が使える環境ではそちらを使います。all
_.some(list, [iterator], [context])listの各要素に対してiteratorを実行し,戻り値が1つでも真なら真を,全て偽なら偽を返します。ネイティブの機能でsome()が使える環境ではそちらを使います。any
_.contains(list, value)listにvalueが含まれていれば真を返します。include
_.invoke(list, methodName, [*arguments])listの各要素に対してmethodNameというメソッドを実行した新しい配列を返します。追加されたargumentsはメソッドの実行時に渡されます。
_.pluck(list, propertyName)listに各要素にpropertyにpropertyNameで指定した値が含まれた新しい配列を返します。_.map()のよく用いられる使われ方です。
_.max(list, [iterator], [context])listの各要素の最大値を返します。iteratorが指定されるとlistに各要素にiteratorを実行し,最大値を返します。
_.min(list, [iterator], [context])listの各要素の最小値を返します。iteratorが指定されるとlistに各要素にiteratorを実行し,最小値を返します。
_.sortBy(list, iterator, [context])listの各要素を,iteratorが指定されるとlistに各要素にiteratorを実行しその値で,文字列でしたらlistの各要素のpropertyの値と同じ文字列のものでソートします。
_.groupBy(list, iterator, [context])listの各要素を,iteratorが指定されるとlistに各要素にiteratorを実行しその値で,文字列でしたらlistの各要素のpropertyの値と同じ文字列のもので分類します。
_.indexBy(list, iterator, [context])listの各要素を,iteratorが指定されるとlistに各要素にiteratorを実行しその値で,文字列でしたらlistの各要素のpropertyの値と同じ文字列のものの値をキーにしたlistを返します。
_.countBy(list, iterator, [context])listの各要素を,iteratorが指定されるとlistに各要素にiteratorを実行しその値で,文字列でしたらlistの各要素のpropertyの値と同じ文字列のもので分類した数を返します。結果の各要素の値は,_.groupBy()の結果の各要素のlengthと同じ値になります。
_.sortedIndex(list, value, [iterator], [context])ソートされたlistに対してvalueの挿入する際のインデックスを返します。
_.shuffle(list)listの各要素を,ランダムに並び替えて返します。
_.sample(list, [n])listの各要素を,ランダムに抜き出して返します。nで返す要素数を指定できます。
_.toArray(list)listを配列として返します。argumentsオブジェクトにたいてい使われます。

 配列の機能

_.first(array, [n])配列の最初の要素を返します。nで返す要素の数を指定できます。head, take
_.initial(array, [n])配列の最後の要素を除いた配列を返します。nで除く要素の数を指定できます。
_.last(array, [n])配列の最後の要素を返します。nで返す要素の数を指定できます。
_.rest(array, [index])配列の最初の要素を除いた配列を返します。indexで除く要素の数を指定できます。tail, drop
_.compact(array)配列から偽となる要素を除いた配列を返します。
_.flatten(array, [shallow])入れ子になった配列をフラットにします。shallowが真の場合,配列の一段目のみフラットにします。
_.without(array, [*values])配列からvaluesを除いた配列を返します。
_.union(*arrays)渡された複数の配列の和集合を返します。
_.intersection(*arrays)渡された複数の配列の積集合を返します。
_.difference(array, *others)配列から配列(others)を除いた配列を返します。
_.uniq(array, [isSorted], [iterator])配列の要素がユニークなもののみ配列にして返します。
_.zip(*arrays)渡された複数の配列を同じインデックスの要素にまとめた配列を返します。
_.object(list, [values])配列をオブジェクトに変換して返します。 [キー,値]のペアの単一のリスト,またはキーのリストと値のリストを渡します。重複したキーが存在する場合は,最後の値が優先されます。
_.indexOf(array, value, [isSorted])配列の要素の中にvalueが存在すればその最初のインデックスを返します。配列の要素の中に存在しない場合は'-1'を返します。ネイティブの機能でindexOf()が使える環境ではそちらを使います。
_.lastIndexOf(array, value, [fromIndex])配列の要素の中にvalueが存在すればその最後のインデックスを返します。配列の要素の中に存在しない場合は'-1'を返します。ネイティブの機能でlastIndexOf()が使える環境ではそちらを使います。
_.range([start], stop, [step])整数の配列を返します。_.map(),_.each()でリストを作成するに便利です。デフォルト値を省略した場合 [start]が0,stepが1になります。

 オブジェクトの機能

メソッド名説明Alias
_.keys(object)オブジェクトのプロパティ名をすべてを返します。
_.values(object)オブジェクトのプロパティ値のすべてを返します。
_.pairs(object)オブジェクトのプロパティ名とプロパティ値を配列のペアにして返します。
_.invert(object)オブジェクトのプロパティ名をプロパティ値に,プロパティ値をプロパティ名にしたオブジェクトのコピーを返します。これが機能するためには,オブジェクト値がすべてユニークで,シリアライズ可能でなければなりません。
_.functions(object)オブジェクトの関数プロパティをソートされた配列で返します。methods
_.extend(destination, *sources)sources'オブジェクトのプロパティを'destination'オブジェクトにコピーして'destination'オブジェクトを返します。⁠sources'オブジェクトに同じプロパティ名を持つ場合は最後のものが上書きされます。
_.pick(object, *keys)オブジェクトからkeysのプロパティ名(whitelist)をもつプロパティを抜き出したオブジェクトのコピーを返します。
_.omit(object, *keys)オブジェクトからkeysのプロパティ名(blacklist)をもつプロパティを除いたオブジェクトのコピーを返します。
_.defaults(object, *defaults)オブジェクトのプロパティで’ defaults⁠オブジェクトのプロパティで未定義のものがあれば上書きしてオブジェクトを返します。
_.clone(object)オブジェクトの浅い (shallow) コピーされたクローンを作成します。ネストされたオブジェクトや配列は,参照によってコピーされ重複しません。
_.tap(object, interceptor)オブジェクトをinterceptorに渡しオブジェクトを返します。_.chainの中間結果に対して実行をする際に主に使われます。
_.has(object, key)オブジェクトにkeyのプロパティ値のオブジェクトがあるか判定します。hasOwnPropertyのショートカットになりますがより安全な参照を行っています。
_.isEqual(object, other)二つのオブジェクトが等しいか深い比較を行い判定します。
_.isEmpty(object)オブジェクトが要素を持っているか判定します。
_.isArray(object)オブジェクトが配列かどうか判定します。
_.isObject(value)渡された値がオブジェクトかどうか判定します。
_.isArguments(object)Argumentオブジェクトか判定します。
_.isFunction(object)関数か判定します。
_.isString(object)文字列か判定します。
_.isNumber(object)数字(NaN含みます)か判定します。
_.isFinite(object)有限数か判定します。
_.isBoolean(object)bool値か判定します。
_.isDate(object)日付オブジェクトか判定します。
_.isRegExp(object)正規表現オブジェクトか判定します。
_.isNaN(object)NaNか判定します。ネイティブのisNaN()はundefinedでも真を返しますが,こちらは偽で判定します。
_.isNull(object)nullか判定します。
_.isUndefined(value)undefinedか判定します。

 関数の機能

メソッド名説明Alias
_.bind(function, object, [*arguments])指定したオブジェクトのコンテキストで関数を束縛(bind)した新しい関数を返します。引数も部分適用(partial application)する事ができます。
_.bindAll(object, *methodNames)オブジェクトの指定したメソッドをオブジェクトのコンテキストで束縛(bind)します。methodNamesを指定しない場合,全てのメソッドが対象です。
_.partial(function, [*arguments])関数に引数の部分適用(partial application)を処理することが出来るカリー化された新しい関数を返します。
_.memoize(function, [hashFunction])引数に渡した関数を結果を??メモ化します。
_.delay(function, wait, [*arguments])引数に渡したミリ秒後に(setTimeoutのように)関数を呼び出します。引数が渡せます。
_.defer(function, [*arguments])引数に渡した関数を現在実行中の処理の最後まで延期して実行します。
_.throttle(function, wait, [options])引数に渡したミリ秒の時間内には一度しか実行しない関数を返します。
_.debounce(function, wait, [immediate])引数に渡したミリ秒経過するまで実行しない関数を返します。
_.once(function)一度だけ実行される関数を返します。二度目以降は実行せず一度目の結果を返します。
_.after(count, function)引数に渡した関数を指定したcountの回数以上実行した場合,実行する関数を返します。
_.wrap(function, wrapper)第一引数の関数を第二引数の関数に渡して実行する関数を返します。
_.compose(*functions)渡した関数のリストを順番に実行して,その結果を次の関数の引数とする関数を返します。

 その他の機能

メソッド名説明Alias
_.noConflict()すでにUnderscore.jsが使用されている場合,既存のものに⁠_⁠変数に渡します。Underscorej.sのオブジェクトを返します。
_.identity(value)引数をそのまま返します。デフォルトのイテレータとしてUnderscore.jsで使われています。
_.times(n, iterator, [context])iteratorをn回実行します。引数にindexを渡します。
_.random(min, max)minとmaxの間のランダムな整数を返します。引数が1つに場合,0からその番号の間の整数を返します。
_.mixin(object)Underscore.jsを拡張できます。
_.uniqueId([prefix])ユニークなIDを生成します。prefixが渡された場合,IDに追加されます。クライアント側のモデルや唯一のDOM要素のために便利です。
_.escape(string)HTMLに挿入するために,文字列&, <, >, ", 'の文字をエスケープします。
_.unescape(string)_.escapeの逆になります。&, <, >, ", 'を置き換えます。
_.result(object, property)objectのpropertyの値が関数である場合,実行して返します,そうでなければ,値を返します。
_.template(templateString, [data], [settings])引数が1つの場合,テンプレートを引数で置き換える関数を返します。第二引数も指定した場合,第二引数を用いてテンプレートを置き換えた文字列を返します。

まとめ

Underscore.jsの機能を一通りご紹介いたしました。

コレクションの処理など便利な機能,関数型プログラミングをはじめたいと考えている方でしたら良いきっかけになるかと思います。

制作者のJeremy Ashkenasは,twitterの自己紹介文で,

"Code is Literature(ソースコードは文学。)"

と記してます。

画像

Underscore.jsはそのままそれが実践されておりソースコードもわかりやすく楽しく読め,個人的にも非常に勉強になりました。

公式サイトでは影響を受けたと思われる,関数や記事なども紹介されています。ちなみに,Underscore.jsのtemplateでのJavaScriptのwithの使い方などは,John Resig(jQueryの開発者)JavaScript Micro-Templatingの記事から影響されたようです。

3回にわたり,⁠Underscore.jsの入り口」につきましてこれで終了になります。短い間でしたがおつきあいありがとうございました。

著者プロフィール

早瀬まこと(はやせまこと)

大規模Webサイトの運用更新にフロントエンドエ ンジニアとして従事しています。

DOMと組み合わせたフロントエンドの開発を主に行っています。

バックナンバー

Underscore.jsの入り口