Underscore.jsの入り口

第2回Underscore.jsのコレクションと配列とオブジェクトの機能

Underscore.jsのコレクションと配列とオブジェクトの機能をご紹介します。

コレクションの機能

Underscore.jsのコレクションの機能をご紹介します。コレクションの機能は配列やオブジェクト、⁠配列のようなオブジェクト」で使えます。

配列のようなオブジェクト

「配列のようなオブジェクト」は配列のように0と正の整数の値をプロパティ名をして持っているオブジェクトです。この「配列のようなオブジェクト」は配列の持つ便利メソッド(join,sliceなど)を直接呼び出せませんが、通常の配列を同じように扱えます。

Argumentsオブジェクト、NodeList オブジェクト(getElementsByTagNameの戻り値)などが「配列のようなオブジェクト」になります。

ここでは、コレクションの主な機能を紹介します。その他の機能につきましては表1に簡単な説明を書きましたので、参考にしていただければと思います。

表1 コレクションの機能
メソッド名説明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を実行し、戻り値が全て真なら真を、一つでも偽なら偽を返します。ネイティブの機能でevery()が使える環境ではそちらを使います。all
_.some(list, [iterator], [context]) listの各要素に対してiteratorを実行し、戻り値が一つでも真なら真を、全て偽なら偽を返します。ネイティブの機能で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オブジェクトにたいてい使われます。

_.each()

書式
_.each(list, iterator, [context])

listの各要素に対してiterator(反復処理を行う関数)を実行します。

iteratorには引数は3つ渡します。引数が配列なら(listの値,listのindex,list)になります。引数がオブジェクトなら(listのプロパティ値,listのプロパティ名,list)になります。引数を1つだけ取るiteratorを記述しても問題ありません。残りの2つは無視されます。ネイティブの機能でforEach()が使える環境ではそちらを使います。

もし [context] オブジェクトが渡されたら、iterator はそれに束縛されます。

下記の例を見ると、iteratorが配列の数の分だけ呼び出されているのがわかります。

_.each( [6,3,1,2], function(val){ alert(val); });
// 6,3,1,2の順でアラート表示されます。

_.each( { six: 6, three: 3, one: 1, two: 2 }, function(val,key,list){ alert('key:' + key + ' val:' + val); });
// key:six val:6,key:three val:3,key:one val:1,key:two val:2の順でアラート表示されます。

_.each()を使うと繰り返しの文がfor文などで表すよりシンプルになり、バグの原因にもなりやすいと言われるループの終了条件の判定などもなくせます。

_.map()

書式
_.map(list, iterator, [context])

_.map()は_.each()と同様に、listの各要素に対してiterator(反復処理を行う関数)を実行します。しかし、_.map()は返ってくる値が_.each()とは異なり、各要素に対してiteratorが返す値を新しい配列として返します。_.map()を使うと配列の変換がシンプルに記述ができます。

ネイティブの機能でmap()が使える環境ではそちらを使います。なお、他の言語ではcollectと呼ばれる場合もあります。

var data = [6,3,1,2];

var data02 = _.map( data, function(val){ return val * 3; });

console.log(data02);
// => [18, 9, 3, 6] 各要素の値に対して3倍した新しい配列が返ります。

var data03 = _.map( {six: 6, three: 3, one: 1, two: 2} , function(val, key){ return val * 3; });

console.log(data03);
// => [18, 9, 3, 6] 各要素に対して3倍した値の配列が返ります。

_.reduce()

書式
_.reduce(list, iterator, memo, [context])

_.reduce()はlistの各要素に対してiteratorを実行し累積結果を返します。これは関数型プログラミングでは普通に行われる処理で、inject、foldと呼ばれることもあります。

iteratorの戻り値は累積結果であり、次の要素に対してiteratorの呼び出しで引数として渡されます。

iteratorの引数は(memo, value)になります。memoが累積結果になります。

ネイティブの機能でreduce()が使える環境ではそちらを使います。

var data = [6,3,1,2];

var product = _.reduce( data, function(memo, value){ return memo*value; }); //値の積
console.log(product);
// => 36

var max = _.reduce( data, function(memo, value){ return (memo > value )? memo : value; }); //値の最大値
console.log(max);
// => 6

_.filter()

書式
_.filter(list, iterator, [context])

listの各要素に対してiteratorを実行し、戻り値が真になる値を抜き出した配列を返します。

ネイティブの機能でfilter()が使える環境ではそちらを使います。

var smallVals = _.filter([1, 2, 3, 4, 5, 6], function(val){ return val log(smallVals);
// => [1, 2] 3より少ない値が新しい配列で返ります。

_.every()と_.some()

書式
_.every(list, [iterator], [context])
_.some(list, [iterator], [context])

_.every()と_.some()はlistの各要素に対してiteratorを実行し判定を行います。

_.every()はlistの各要素に対してiteratorを実行し、戻り値がすべて真なら真を、1つでも偽なら偽を返します。

ネイティブの機能でevery()が使える環境ではそちらを使います。

var data = [6,3,1,2];

//すべての値が10より大きい
var result = _.every( data, function(value){ return value log(result);
// => true

_.some()はlistの各要素に対してiteratorを実行し、戻り値が1つでも真なら真を、すべて偽なら偽を返します。

ネイティブの機能でsome()が使える環境ではそちらを使います。

var data = [6,3,1,2];

//値が偶数を含む
var result = _.some( data, function(value){ return value%2 === 0 ; });
console.log(result);
// => true

配列の機能

Underscore.jsの配列の機能についてご紹介します。配列の機能はargumentsオブジェクトでも動作します。また、Underscore.jsの配列の機能は「疎な配列」で動作するようには設計されていません。

疎な配列

疎な配列とは配列の要素が0から順に埋まっていない配列になります。

その他の機能につきましては表2に簡単な説明を書きましたので、参考にしていただければと思います。

表2 配列の機能
メソッド名説明Alias
_.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になります。

_.compact()

書式
_.compact(array)

配列から偽となる要素を除いた配列を返します。偽の判定は、false, null, 0, "", undefined ,NaNになります。

var smallVals = _.filter([1, 2, 3, 4, 5, 6], function(val){ return val log(smallVals);
// => [1, 2] 3より少ない値が新しい配列で返ります。

_.union()と_.intersection()

書式
_.union(*arrays)
_.intersection(*arrays)

_.union()と_.intersection()は渡された複数の配列をまとめます。_.union()は渡された複数の配列の和集合を返します。

var data01 = [3, 22, 23, 6, 1];
var data02 = [1, 3, 22, 5];
var data03 = [6, 9, 1, 22, 3];

var unionData = _.union( data01, data02, data03 );
console.log(unionData);
//=> [3, 22, 23, 6, 1, 5, 9]

_.intersection()は渡された複数の配列の積集合を返します。

var data01 = [3, 22, 23, 6, 1];
var data02 = [1, 3, 22, 5];
var data03 = [6, 9, 1, 22, 3];

var intersectionData = _.intersection( data01, data02, data03 );
console.log(intersectionData);
//=> [3, 22, 1]

_.indexOf()

書式
_.indexOf(array, value, [isSorted])

配列の要素の中にvalueが存在すればその最初のインデックスを返します。

配列の要素の中に存在しない場合は⁠-1⁠を返します。配列がすでにソートされていれば[isSorted]にtrueを渡し、より速い検索を行えます。

ネイティブの機能でindexOf()が使える環境ではそちらを使います。

var idx = _.indexOf([3, 22, 23, 6, 1, 4, 6], 6);
console.log(idx);
=> 3

_.range()

書式
_.range([start], stop, [step])

整数の配列を返します。_.map()、_.each()でリストを作成するに便利です。デフォルト値を省略した場合 [start]が0、stepが1になります。

var data01 = _.range(10);
console.log(data01);
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

var data02 = _.range(1, 11);
console.log(data02);
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

var data03 = _.range(0, 30, 5);
console.log(data03);
//=> [0, 5, 10, 15, 20, 25]

オブジェクトの機能

Underscore.jsのオブジェクトの主な機能を紹介します。プロパティの操作が便利になるものが用意されています。

その他の機能につきましては表3に簡単な説明を書きましたので、参考にしていただければと思います。

表3 オブジェクトの機能
メソッド名説明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か判定します。

_.keys()と_.values()

書式
_.keys(object)
_.values(object)

_.keys()と_.values()はオブジェクトのプロパティ名、プロパティ値を返します。_.keys()はオブジェクトのプロパティ名をすべてを返します。

var pNames = _.keys({name: 'makoto', message: 'hello!!!' });
console.log(pNames);
//=> ["name", "message"]

_.values()はオブジェクトのプロパティ値のすべてを返します。

var pVals = _.values({name: 'makoto', message: 'hello!!!' });
console.log(pVals);
//=> ["makoto", "hello!!!"]

_.extend()

書式
_.extend(destination, *sources)

sourcesオブジェクトのプロパティをdestinationオブジェクトにコピーしてdestinationオブジェクトを返します。sourcesオブジェクトに同じプロパティ名を持つ場合は最後のものが上書きされます。

var obj = { name: 'makoto', message: 'hello!!!' };
var extend_obj = { hobby :['読書','散歩'] };

_.extend(obj, extend_obj);

console.log(obj);
//=> { name: 'makoto', message: 'hello!!!', hobby :['読書','散歩'] }

_.defaults()

書式
_.defaults(object, *defaults)

オブジェクトのプロパティでdefaultsオブジェクトのプロパティの未定義(undefined)のものがあれば上書きしてオブジェクトを返します。

var defaults_obj = { name: 'John Q', message: 'hi!!', };
var obj = { name: 'makoto' };

_.defaults(data, defaults_obj);

console.log(obj);
//=> {name: "makoto", message: "hi!!"}

_.isArray()

書式
_.isArray(object)

配列でしたら真を返します。

ネイティブの機能でArray.isArray()が使える環境ではそちらを使います。

var result = (function(){ return _.isArray(arguments); })();
conosle.log(result);
//=> false  argumentsオブジェクトは配列ではなく"配列のようなオブジェクト"のため偽を返します。

_.isArray([1,2,3]);
=> true 配列なので真を返します。

まとめ

Underscore.jsのコレクションと配列、オブジェクトの機能の紹介をさせていただきました。これらの機能を使えばコレクションの操作、判定なども容易になると思います。

次回は

  • 関数の機能
  • ユーテリティ(テンプレート等)
  • Chaining

を紹介する予定です。次回もよろしくお願いします。

おすすめ記事

記事・ニュース一覧