便利なUnderscore.js の関数とサンプルコード

underscorejs

Underscore.jsは、便利なユーティリティ関数を詰め合わせたJavascriptライブラリです。複雑なアルゴリズムを簡単なコードで書くことが出来るようになりますが、ある程度、覚えてないと利用することも出来ないので一覧にして時間のあるとき眺めて覚えておくと役に立つと思います。

主な種類

  • コレクション
  • 配列
  • 関数
  • オブジェクト
  • ユーティリティ
  • チェーン

コレクション

each

listの要素をイテレートする。すべての要素はiterator関数にyieldされる。 iteratorには(element, index, list)の3つの引数が渡される。もしlistがJavascript Objectだった場合は(value, key, list)になる。

_.each([1, 2, 3], function(num){ alert(num); });
 => alerts each number in turn...
 _.each({one : 1, two : 2, three : 3}, function(num, key){ alert(num); });
 => alerts each number in turn...

map

listのすべての要素を操作関数(iterator)でマッピングし、新しい配列を作る。もしlistがJavascript Objectだった場合、iteratorへの引数は(value, key, list)になる。

_.map([1, 2, 3], function(num){ return num * 3; });
 => [3, 6, 9]
 _.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
 => [3, 6, 9]

reduce

listの要素を1つの値に集約する。memoが初期値。iteratorはステップごとに値を返さなければいけない。

var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
 => 6

reduceRight

右方向からのreduce。

var list = [[0, 1], [2, 3], [4, 5]];
 var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
 => [4, 5, 2, 3, 0, 1]

find

リストの要素の中から、一番最初に真値テスト(iterator)を通過したものを返す。

var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 => 2

filter

リストの要素の中から、真値テスト(iterator)を通過したものを返す。

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 => [2, 4, 6]

reject

リストの要素の中から、真値テスト(iterator)を通過しなかったものを返す。selectの反対。

var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
 => [1, 3, 5]

all

リストの要素がすべて真値テスト(iterator)を通過した場合、trueを返す。そうでない場合はfalseを返す。iteratorが与えられなかった場合、代わりに真理値が使用される。

_.all([true, 1, null, 'yes'], _.identity);
 => false

any

listの要素が1つでも真値テストを通過した場合、trueを返す。そうでない場合はfalseを返す。

_.any([null, 0, 'yes', false]);
 => true

include

valueがlistに含まれている場合、trueを返す。そうでない場合はfalseを返す。値の比較は===演算子で行われる。

_.include([1, 2, 3], 3);
 => true

invoke

listの各要素に対してmethodNameで指定した関数を実行する。*argumentsは、指定された関数に引き渡される。

_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
 => [[1, 5, 7], [1, 2, 3]]

pluck

mapの便利バージョン。指定したプロパティ名に対応する値を集める。

var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
 _.pluck(stooges, 'name');
 => ["moe", "larry", "curly"]

max

listの中の最大値を求める。iteratorが渡された場合、iteratorの返り値がランク付けの基準として使用される。

var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
 _.max(stooges, function(stooge){ return stooge.age; });
 => {name : 'curly', age : 60};

min

listの中の最小値を求める。iteratorが渡された場合、iteratorの返り値がランク付けの基準として使用される。

var numbers = [10, 5, 100, 2, 1000];
 _.min(numbers);
 => 2

sortBy

各要素をiteratorの返り値でランク付けし、それと元にソートされたlistを返す。

_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
 => [5, 4, 6, 3, 1, 2]

groupBy

list を2つに別ける

_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
 => {1: [1.3], 2: [2.1, 2.4]}
 _.groupBy(['one', 'two', 'three'], 'length');
 => {3: ["one", "two"], 5: ["three"]}

sortedIndex

二分探索で、valueがlistの挿入されるべき位置を調べ、それを返す。iteratorが渡された場合、iteratorの返り値がランク付けの基準として使用される。

_.sortedIndex([10, 20, 30, 40, 50], 35);
 => 3

shuffle

ランダムに並び替える

_.shuffle([1, 2, 3, 4, 5, 6]);
 => [4, 1, 6, 3, 5, 2]

toArray

list(イテレートできるものならなんでも)をArrayに変換する。引数を変形するのに便利。

 (function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
 => [2, 3, 4]

size

listに含まれている要素の数を返す。

_.size({one : 1, two : 2, three : 3});
 => 3

配列

first

配列の一番目の要素を返す。nを指定しすると、先頭からn番目の要素までの配列を返す。

_.first([5, 4, 3, 2, 1]);
 => 5

initial

_.initial([5, 4, 3, 2, 1]);
 => [5, 4, 3, 2]

last

配列の最後にある要素を返す。

_.last([5, 4, 3, 2, 1]);
 => 1

rest

先頭の要素を取り除いた配列を返す。indexを指定すると、index番目以降の要素を配列として返す。

_.rest([5, 4, 3, 2, 1]);
 => [4, 3, 2, 1]

compact

曖昧な値であるfalse, null, 0, “”, undefinedを取り除いた配列を返す。非破壊的。

_.compact([0, 1, false, 2, '', 3]);
 => [1, 2, 3]

flatten

多次元配列を一次元化する。非破壊的。

_.flatten([1, [2], [3, [[4]]]]);
 => [1, 2, 3, 4];
 _.flatten([1, [2], [3, [[4]]]], true);
 => [1, 2, 3, [[4]]];

without

valuesを取り除いた配列を返す。===演算子で比較される。非破壊的。

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
 => [2, 3, 4]

union

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
 => [1, 2, 3, 101, 10]

intersection

複数の配列の共通集合を返す。

_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
 => [1, 2]

difference

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
 => [1, 3, 4]

uniq

配列から重複を取り除く。===演算子で比較される。配列がソートされている場合は、isSrotedをtrueにすると処理が早くなる。非破壊的。

_.uniq([1, 2, 1, 3, 1, 4]);
 => [1, 2, 3, 4]

zip

複数の配列の、同じ位置にある要素をマージする。

_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
 => [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]

indexOf

配列にvalueが含まれていた場合、valueが一番最初に現れた位置を返す。含まれていなかった場合は-1を返す。配列がソートされている場合は、isSrotedをtrueにすると処理が早くなる。

_.indexOf([1, 2, 3], 2);
 => 1

lastIndexOf

配列にvalueが含まれていた場合、valueが一番最後に現れた位置を返す。含まれていなかった場合は-1を返す。

_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
 => 4

range

startからstopまでstepずつ増加(または減少)する整数のリストを作る。排他的。 startのデフォルト値は0。stepのデフォルト値は1。

_.range(10);
 => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 _.range(1, 11);
 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 _.range(0, 30, 5);
 => [0, 5, 10, 15, 20, 25]
 _.range(0, -10, -1);
 => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
 _.range(0);
 => []

関数

bind

オブジェクトを関数にバインドする。関数が呼ばれたとき、thisがobjectの値をとるということ。カリー化。

var func = function(greeting){ return greeting + ': ' + this.name };
 func = _.bind(func, {name : 'moe'}, 'hi');
 func();
 => 'hi: moe'

bindAll

複数の関数をオブジェクトにバインドする。イベントハンドラーに関数をバインドするときに便利。

var buttonView = {
   label   : 'underscore',
   onClick : function(){ alert('clicked: ' + this.label); },
   onHover : function(){ console.log('hovering: ' + this.label); }
 };

 _.bindAll(buttonView);
 jQuery('#underscore_button').bind('click', buttonView.onClick);
 => When the button is clicked, this.label will have the correct value...

memoize

関数の計算結果をキャッシュする。メモ化。hasFunctionが指定された場合、結果をストアするためのハッシュキーとして利用される。hasFunctionのデフォルト値は一番最初の引数。

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

delay

setTimeoutのように、ミリ秒後に関数を呼び出す。argumentsを指定した場合、それが呼び出される関数に引き渡される。

var log = _.bind(console.log, console);
 _.delay(log, 1000, 'logged later');
 => 'logged later' // Appears after one second.

defer

コールスタックが空になるまで、関数の呼び出しを遅延させる。delay = 0でsetTimeoutを使う場合と同じ。複雑な計算を行ったり、UIスレッドをブロックせずにまとまったHTMLレンダリングを行いたいときに便利。

_.defer(function(){ alert('deferred'); });
 // Returns from the function before the alert runs.

throttle

スロットル化された関数を返す。ラップされた関数はwaitミリ秒に多くても一度しか実行されない。レートが制限されたイベントを起こすのに便利。

var throttled = _.throttle(updatePosition, 100);
 $(window).scroll(throttled);

debounce

関数が実行されてからwaitミリ秒が経過するまで、繰り返しの呼び出しを抑止する。何らかの入力がストップしたときに実行される振る舞いを実装したいときに便利。

var lazyLayout = _.debounce(calculateLayout, 300);
 $(window).resize(lazyLayout);

once

一度しか実行されない関数を作成する。修正された関数の二度目以降の呼び出しは、なんの影響も与えず、最初に呼び出されたときの返り値を返す。初期化処理に便利。

var initialize = _.once(createApplication);
 initialize();
 initialize();

after

var renderNotes = _.after(notes.length, render);
 _.each(notes, function(note) {
   note.asyncSave({success: renderNotes});
 });

wrap

最初の引数で指定した関数をwrapper関数の中にラップする。wrapper関数には指定された関数の実行の前後で行われる処理を記述することができる。

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

compose

複数の関数の合成関数を返す。関数は次の関数の返り値を引数としてとる。関数f(), g(), h()を合成しすると関数f(g(h()))ができる。

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

オブジェクト

keys

objectのプロパティ名をすべて取り出す。

_.keys({one : 1, two : 2, three : 3});
 => ["one", "two", "three"]

values

objectのプロパティ値をすべて取り出す。

_.values({one : 1, two : 2, three : 3});
 => [1, 2, 3]

functions

objectが持つすべての関数プロパティ名をソートして返す。

_.functions(_);
 => ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...

extend

soucesオブジェクトのすべてのプロパティをdestinationオブジェクトにコピーする。sourcesの中に同じ名前のプロパティが含まれていた場合、より後のもので上書きされる。

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

pick

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

defaults

objectがdefaultsオブジェクトのプロパティを持っていない場合、objectにそのdefaultsオブジェクトのプロパティを付与する。

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

clone

objectのシャローコピーうを作る。ネストされたオブジェクトや配列は、参照コピーされる。

_.clone({name : 'moe'});
 => {name : 'moe'};

tap

_.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]

has

_.has({a: 1, b: 2, c: 3}, "b");
 => true

isEqual

var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
 var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
 moe == clone;
 => false
 _.isEqual(moe, clone);
 => true

isEmpty

_.isEmpty([1, 2, 3]);
 => false
 _.isEmpty({});
 => true

isElement

_.isElement(jQuery('body')[0]);
 => true

isArray

 (function(){ return _.isArray(arguments); })();
 => false
 _.isArray([1,2,3]);
 => true

isObject

_.isObject({});
 => true
 _.isObject(1);
 => false

isArguments

 (function(){ return _.isArguments(arguments); })(1, 2, 3);
 => true
 _.isArguments([1,2,3]);
 => false

isFunction

_.isFunction(alert);
 => true

isString

_.isString("moe");
 => true

isNumber

_.isNumber(8.4 * 5);
 => true

isFinite

_.isFinite(-101);
 => true
 _.isFinite(-Infinity);
 => false

isBoolean

_.isBoolean(null);
 => false

isDate

_.isDate(new Date());
 => true

isRegExp

_.isRegExp(/moe/);
 => true

isNaN

_.isNaN(NaN);
 => true
 isNaN(undefined);
 => true
 _.isNaN(undefined);
 => false

isNull

_.isNull(null);
 => true
 _.isNull(undefined);
 => false

isUndefined

_.isUndefined(window.missingVariable);
 => true

ユーティリティ

noConflict

var underscore = _.noConflict();

identity

var moe = {name : 'moe'};
 moe === _.identity(moe);
 => true

times

(3).times(function(){ genie.grantWish(); });

mixin

_.mixin({
   capitalize : function(string) {
     return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
   }
 });
 _("fabio").capitalize();
 => "Fabio"

uniqueId

_.uniqueId('contact_');
 => 'contact_104'

escape

 _.escape('Curly, Larry & Moe');
 => "Curly, Larry &amp; Moe"

result

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

template

var compiled = _.template("hello: <%= name %>");
 compiled({name : 'moe'});
 => "hello: moe"

 var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
 _.template(list, {people : ['moe', 'curly', 'larry']});
 => "<li>moe</li><li>curly</li><li>larry</li>"

 var template = _.template("<b><%- value %></b>");
 template({value : '<script>'});
 => "<b>&lt;script&gt;</b>"

 var compiled = _.template("<% print('Hello ' + epithet); %>");
 compiled({epithet: "stooge"});
 => "Hello stooge."

 _.templateSettings = {
   interpolate : /\{\{(.+?)\}\}/g
 };

 var template = _.template("Hello {{ name }}!");
 template({name : "Mustache"});
 => "Hello Mustache!"

 _.template("Using 'with': <%= data.answer %>", {answer: 'no'}, {variable: 'data'});
 => "Using 'with': no"

 <script>
   JST.project = <%= _.template(jstText).source %>;
 </script>

チェーン

chain

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"

value

([1, 2, 3]).value();
 => [1, 2, 3]

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。