underscore.
関数の機能
JavaScriptで関数型プログラミングのテクニックが使いやすくなる便利な関数が揃っています。引数に1つ以上の関数を受け取り、
今回は、
_.bind()
- 書式
- _.bind(function, object, [*arguments])
指定したobjectにfunctionを束縛(bind)して新しい関数を返します。よって新しい関数の中で使われるthisは指定したobjectになります
argumentsを渡した場合は引数も部分適用
var message = function(greeting){
return greeting + this.name + '!!!'
};
var hello_message = _.bind(message, {name: 'makoto'}, 'hello!!');
//message関数を指定したオブジェクトで束縛(bind)する
hello_message();
//=> 'hello!!makoto!!!'
- 関数の部分適用
(partial application) 関数型プログラミングで紹介されるテクニックの1つです。既存の関数に引数をあらかじめ指定して新しい関数
(ラッパー関数) を作ります。同様の関数をほとんど同じ引数で使っていたらその関数は部分適用する候補になります。
_.partial()
- 書式
- _.partial(function, [*arguments])
指定した関数の引数を部分適用した新しい関数を返します。
var add = function(a, b) { return a * b; };
add(16,11);
//=> 176
//add関数の引数aを部分適用します。
var add11 = _.partial(add, 11);
add11(16);
//=> 176
var message = function(greeting){
return greeting + ' ようこそお越し下さいました。'
};
//message関数の引数をそれぞれ部分適用します。
var daytime_message = _.partial(message,'こんにちは');
var night_message = _.partial(message,'こんばんは');
daytime_message();
//=> "こんにちは ようこそお越し下さいました。"
night_message();
//=> "こんばんは ようこそお越し下さいました。"
_.memoize()
- 書式
- _.memoize(function, [hashFunction])
引数に渡したfunctionの結果をメモ化する関数として新しく返します。2回目からは問い合わせ内容がキャッシュされるので結果を返すのが高速化されます。
第2引数のhashFunctionはメモ化する際にメモ化されるデータのキーを設定するために使われます。デフォルトでは_.identityにfunctionの引数を渡したものがメモ化されるデータのキーとして使われます。
・メモ化一度呼び出された結果をそのときの引数と共に記憶しておき、
下記、
//データになります。
var members = [
{ 'name': 'chiba', 'age': 25 },
{ 'name': 'kuhara', 'age': 24 },
{ 'name': 'abe', 'age': 26 },
{ 'name': 'ueno', 'age': 27 }
];
//データを取得する関数です
var get = function(name){
return _.find(members,
function(member){
return member.name == name;
})
};
//データが取得できます。
get('chiba');
// => {name: "chiba", age: 25}
//メモ化関数をかえします。
var getmemo = _.memoize(get);
//データが取得できます。データがキャッシュされます。
getmemo('chiba');
// => {name: "chiba", age: 25}
//二回目以降はキャッシュから取得します。
getmemo('chiba');
// => {name: "chiba", age: 25}
//フィボナッチ数列の計算のメモ化の例です。
var fibonacci = _.memoize(function(n) {
return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});
ユーティリティの機能
その他の便利なユーティリティの機能をご紹介します。エスケープ処理やテンプレート機能などが用意されています。機能につきましては、
_.uniqueId()
- 書式
- _.uniqueId([prefix])
ユニークなIDを生成します。
prefixが渡された場合、
クライアント側のモデルや唯一のDOM要素のために便利です。
_.uniqueId('cont_');
//=> cont_10
_.uniqueId('cont_');
//=> cont_11
_.uniqueId('cont_');
//=> cont_12
_.escape()
- 書式
- _.escape(string)
HTMLに挿入するために、
var str = '"Asai", "Nakamura", & "Terui"';
_.escape(str);
//=> "Asai", "Nakamura", & "Terui"
_.unescape()
- 書式
- _.unescape(string)
HTMLに挿入するためにエスケープされた文字列を置換してもとに戻します。
var str = '"Asai", "Nakamura", & "Terui"';
_.unescape(str);
//=> "Asai", "Nakamura", & "Terui"
_.template()
- 書式
- _.template(templateString, [data], [settings])
テンプレート
テンプレート関数の置き換えは
<%= %>
で行います。
下記は例になります。
var template = _.template("hello! <%= name %>!!");
template({name: 'ai'});
//=> hello! ai!!
ただし実際にHTMLのテンプレート関数を作成する際は上記ではエスケープは行われないため、
<%- %>
で行ってください。 上記の指定で_.escape()を適用します。
下記は例になります。
var span_template = _.template("<span><%- span_val %></span>");
span_template({span_val: '<script type="text/javascript" src="underscore.js"></script>'});
//=> <span><script type="text/javascript" src="underscore.js"></script></span>
JavaScriptの制御構文も入れる事ができます。
<% %>
で行ってください。コレクションの置き換えなどができます。
下記は例になります。
var members = [
{ 'name': 'chiba', 'age': 25 },
{ 'name': 'kuhara', 'age': 24 },
{ 'name': 'abe', 'age': 26 },
{ 'name': 'ueno', 'age': 27 }
];
var list = "<ui>" +
"<% _.each(members, function(member) { %>" +
"<li><%- member.name %>:<%- member.age %></li>" +
"<% }); %>" +
"</ui>";
_.template(list, members);
//=> <ui><li>chiba:25</li><li>kuhara:24</li><li>abe:26</li><li>ueno:27</li></ui>
Chainingの機能
Chainingの機能をご紹介します。Chainingは、
_.chain()
- 書式
- _.chain(object)
objectをラップしたオブジェクトを返し、
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の戻り値は累積結果であり、 | inject, foldl |
_.reduceRight(list, iterator, memo, [context]) | _.reduce()と同等の処理をlistの最後から実行します。ネイティブの機能でreduceRight()が使える環境ではそちらを使います。 | foldr |
_.find(list, iterator, [context]) | listの各要素に対してiteratorを実行し、 | detect |
_.filter(list, iterator, [context]) | listの各要素に対してiteratorを実行し、 | |
_.where(list, properties) | listの各要素に対してiteratorを実行し、 | |
_.findWhere(list, properties) | listの各要素に対してiteratorを実行し、 | |
_.reject(list, iterator, [context]) | listの各要素に対してiteratorを実行し、 | |
_.every(list, [iterator], [context]) | listの各要素に対してiteratorを実行し、 | all |
_.some(list, [iterator], [context]) | listの各要素に対してiteratorを実行し、 | 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の各要素を、 | |
_.groupBy(list, iterator, [context]) | listの各要素を、 | |
_.indexBy(list, iterator, [context]) | listの各要素を、 | |
_.countBy(list, iterator, [context]) | listの各要素を、 | |
_.sortedIndex(list, value, [iterator], [context]) | ソートされたlistに対してvalueの挿入する際のインデックスを返します。 | |
_.shuffle(list) | listの各要素を、 | |
_.sample(list, [n]) | listの各要素を、 | |
_.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) | 配列から配列 | |
_.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()、 |
メソッド名 | 説明 | Alias |
---|---|---|
_.keys(object) | オブジェクトのプロパティ名をすべてを返します。 | |
_.values(object) | オブジェクトのプロパティ値のすべてを返します。 | |
_.pairs(object) | オブジェクトのプロパティ名とプロパティ値を配列のペアにして返します。 | |
_.invert(object) | オブジェクトのプロパティ名をプロパティ値に、 | |
_.functions(object) | オブジェクトの関数プロパティをソートされた配列で返します。 | methods |
_.extend(destination, *sources) | ’sources'オブジェクトのプロパティを'destination'オブジェクトにコピーして'destination'オブジェクトを返します。’sources'オブジェクトに同じプロパティ名を持つ場合は最後のものが上書きされます。 | |
_.pick(object, *keys) | オブジェクトからkeysのプロパティ名 | |
_.omit(object, *keys) | オブジェクトからkeysのプロパティ名 | |
_.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) | 数字 | |
_.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)した新しい関数を返します。引数も部分適用 | |
_.bindAll(object, *methodNames) | オブジェクトの指定したメソッドをオブジェクトのコンテキストで束縛(bind)します。methodNamesを指定しない場合、 | |
_.partial(function, [*arguments]) | 関数に引数の部分適用 | |
_.memoize(function, [hashFunction]) | 引数に渡した関数を結果を??メモ化します。 | |
_.delay(function, wait, [*arguments]) | 引数に渡したミリ秒後に | |
_.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. | |
_.identity(value) | 引数をそのまま返します。デフォルトのイテレータとしてUnderscore. | |
_.times(n, iterator, [context]) | iteratorをn回実行します。引数にindexを渡します。 | |
_.random(min, max) | minとmaxの間のランダムな整数を返します。引数が1つに場合、 | |
_.mixin(object) | Underscore. | |
_.uniqueId([prefix]) | ユニークなIDを生成します。prefixが渡された場合、 | |
_.escape(string) | HTMLに挿入するために、 | |
_.unescape(string) | _.escapeの逆になります。&, <, >, ", 'を置き換えます。 | |
_.result(object, property) | objectのpropertyの値が関数である場合、 | |
_.template(templateString, [data], [settings]) | 引数が1つの場合、 |
まとめ
Underscore.
コレクションの処理など便利な機能、
制作者のJeremy Ashkenasは、
"Code is Literature
(ソースコードは文学。) "
と記してます。
![画像](/assets/images/dev/serial/01/underscorejs/0003/thumb/TH800_001.png)
Underscore.
公式サイトでは影響を受けたと思われる、
3回にわたり、