JavaScript‎ > ‎

Underscore.js

https://github.com/enja-oss/Underscoreに新しい訳があります。

Underscore はJavaScript用ユーティリティベルトライブラリです。 Prototype.js (やRuby)では当然と考えるたくさんの関数プログラミングサポートを提供します。しかし、組み込みJavaScriptオブジェクトのどれも拡張することはしません。 jQueryというタキシードに合わせたネクタイです。

Underscore は60余りの関数を提供します。それらの関数は、関数型のいつもの用注意人物: mapselectinvoke — はもちろん、関数束縛、javascriptテンプレート、深い同等性テストなどさらに専門化したヘルパどちらもサポートします。組み込み関数がもし存在すれば、それらに委譲します。だからモダンなブラウザは forEach や, mapreducefiltereverysomeindexOf のネイティブな実装を使います。

あなたに精読してもらうように、完全な テスト&ベンチマークスイート が含まれています。

注釈付きソースコード も通読できます。

このプロジェクトは GitHub上にホストされています。問題ページ上やFreenode上の #documentcloud チャンネル内でバグを報告したり特徴を議論したりできますし、 @documentcloudにツィートを送ることもできます。

Underscore は DocumentCloud のオープンソースコンポーネントです。

ダウンロード (右クリックして「別名で保存」を使ってください)

開発バージョン (1.2.2) 34kb, コメント付き非圧縮版
製品バージョン (1.2.2) < 4kb, 最小化版

目次

オブジェクト指向と関数型スタイル

コレクション 
eachmapreducereduceRightfindfilterrejectallanyinclude,invokepluckmaxminsortBygroupBysortedIndexshuffletoArray,size

配列 
firstinitiallastrestcompactflattenwithoutunionintersection,differenceuniqzipindexOflastIndexOfrange

関数 
bindbindAllmemoizedelaydeferthrottledebounceonceafter,wrapcompose

オブジェクト 
keysvaluesfunctionsextenddefaultsclonetapisEqualisEmpty,isElementisArrayisArgumentsisFunctionisStringisNumber,isBooleanisDateisRegExp isNaNisNullisUndefined

ユーティリティ 
noConflictidentitytimesmixinuniqueIdescapetemplate

チェーン 
chainvalue

オブジェクト指向と関数型スタイル

Underscore は、好みに合わせてオブジェクト指向スタイルでも関数型スタイルでも使うことができます。以下の2行のコードは数字のリストを二倍にする全く同じ方法です。

_.map([1, 2, 3], function(n){ return n * 2; });
_([1, 2, 3]).map(function(n){ return n * 2; });

オブジェクト指向スタイルを使うとメソッドを繋ぎ合わせることができます。ラップされたオブジェクト上で chain をコールすると、続くメソッドすべても同様にラップされたオブジェクトを返します。計算を終わらせる時は value を使って最終的な値を取り出してください。以下は歌の中の単語の出現回数を得るために map/flatten/reduce を一緒に繋ぎ合わせた例です。

var lyrics = [
  {line : 1, words : "I'm a lumberjack and I'm okay"},
  {line : 2, words : "I sleep all night and I work all day"},
  {line : 3, words : "He's a lumberjack and he's okay"},
  {line : 4, words : "He sleeps all night and he works all day"}
];

_(lyrics).chain()
  .map(function(line) { return line.words.split(' '); })
  .flatten()
  .reduce(function(counts, word) {
    counts[word] = (counts[word] || 0) + 1;
    return counts;
}, {}).value();

=> {lumberjack : 2, all : 4, night : 2 ... }

さらに、配列プロトタイプのメソッドはチェーンされたUnderscoreオブジェクトを通して代理されるので、チェーンの中に reverse や push をさっと入れて続けて配列を修正できます。

コレクション関数 (配列またはオブジェクト)

each_.each(list, iterator, [context]) エーリアス: forEach 
要素の list 上で反復適用し、それぞれを順に iterator 関数に与えます。もし context オブジェクトが渡されたら、iterator はそれに束縛されます。iterator の呼び出しそれぞれは3つの引数(element, index, list)を伴ってコールされます。 list が JavaScript オブジェクトなら iterator の引数は (value, key, list)  になります。ネイティブの forEach 関数があれば、それに委譲します。

_.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_.map(list, iterator, [context]) 
list の中の値それぞれを変換関数 (iterator) を通して写像した値の新たな配列を生成します。ネイティブな map メソッドがあれば、それを代わりに使います。list がJavaScript オブジェクトなら、 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_.reduce(list, iterator, memo, [context]) エーリアス: inject, foldl 
inject や foldl としても知られていますが、 reduce は値の list を1つの値に圧縮します。 memo は換算の初期状態で、iterator は換算のそれぞれのステップを返さなければいけません。 

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

reduceRight_.reduceRight(list, iterator, memo, [context]) エーリアス: foldr 
reduce の右結合版。 JavaScript 1.8 バージョンの reduceRight があれば、それに委譲します。 foldr は遅延評価を持つ言語ほどには JavaScript では役に立ちません。

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_.find(list, iterator, [context]) エーリアス: detect 
list の中のそれぞれの値を見て、真値テスト (iterator) をパスする最初の値を返します。 関数は条件を満たす要素を見つけるとすぐに戻り、リスト全体を横断しません。

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

filter_.filter(list, iterator, [context]) エーリアス: select 
list の中のそれぞれの値を見て、真値テスト (iterator) をパスする値すべての配列を返します。 ネイティブな filter メソッドがあれば、それに委譲します。

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

reject_.reject(list, iterator, [context]) 
真値テスト (iterator) をパスする要素をの除いた list の値を返します。filter の反対です。

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

all_.all(list, iterator, [context]) エーリアス: every 
list の値すべてが iterator 真値テストをパスしたら true を返します。ネイティブなメソッド every があればそれに委譲します。

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

any_.any(list, [iterator], [context]) エーリアス: some 
list の値のどれかが iterator 真値テストをパスしたら true を返します。真の要素が見つかったら後の処理は省略してリストを横断することを止めます。ネイティブなメソッド some があればそれに委譲します。

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

include_.include(list, value) エーリアス: contains 
同等性をテストするのに === を使って、 list の中に value があれば true を返します。 list が配列なら内部では indexOf を使います。

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

invoke_.invoke(list, methodName, [*arguments]) 
list. の中のそれぞれの値に対して methodName で指名されたメソッドをコールします。  invoke に渡される他の引数はメソッド呼び出しに転送されます。

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

pluck_.pluck(list, propertyName) 
たぶん map の最も見かけるユースケースであるもののお手軽版: プロパティ値のリストの抽出。

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

max_.max(list, [iterator], [context]) 
list の中の最大値を返します。 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_.min(list, [iterator], [context]) 
list の中の最小値を返します。 iterator が渡されたら、それぞれの値に対して値をランク付けする基準を生成するのに使われます。

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

sortBy_.sortBy(list, iterator, [context]) 
それぞれの値を iterator に通した結果でランク付けした順に並び替えられたlist のコピーを返します。

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

groupBy_.groupBy(list, iterator) 
コレクションをそれぞれの値を iterator に通した結果でグループ化した組に分けます。  iterator が関数ではなく文字列なら、値のそれぞれに対する iterator と名付けられたプロパティでグループ化します。

_.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_.sortedIndex(list, value, [iterator]) 
二分木探索を使って、 list の並び順を維持するように value を list に挿入すべきインデックスを決定します。 iterator が渡されたら、それぞれの値の並びのランク付けを計算するのにそれを使います。

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

shuffle_.shuffle(list) 
list のシャッフルされたコピーを返します。 Fisher-Yates シャッフル のあるバージョンを使っています。

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

toArray_.toArray(list) 
list (その上でイテレートできるものならなんでも) を本当の配列に変換します。 arguments オブジェクトを変形するのに有用です。

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

size_.size(list) 
list の中の値の数を返します。

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

Array Functions

注意: すべての配列関数は arguments オブジェクトに対しても機能します。

first_.first(array, [n]) エーリアス: head 
array の一番目の要素を返します。 n を渡すと配列の最初の 個の要素を返します。

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

initial_.initial(array, [n]) 
配列の最後の要素以外のすべてを返します。特に arguments オブジェクトに対して有用です。最後の n 要素を結果から除外するには n を渡してください。

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

last_.last(array, [n]) 
array の最後の要素を返します。  n を渡すと配列の最後の n 個の要素を返します。

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

rest_.rest(array, [index]) エーリアス: tail 
配列の中の要素の残り(rest) を返します。配列のそのインデックス以降の値を返すには index を渡してください。

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

compact_.compact(array) 
偽となる(falsy)値をすべて除いた array のコピーを返します。JavaScript では, false と,null0""undefined, NaN はすべて偽となります。

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

flatten_.flatten(array) 
入れ子の array をフラットにします。(入れ子はどんな深さでも問題ないです。)

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

without_.without(array, [*values]) 
values のインスタンスすべてを除いた array のコピーを返します。 同等性テストには === が使われます。

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

union_.union(*arrays) 
arrays の和集合 (arrays のどれかか複数で現れる項目を1回だけ順にとったリスト)を計算します。

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

intersection_.intersection(*arrays) 
arrays すべての積集合となる値のリストを計算します。結果の中のそれぞれの値はそれぞれの arrays に現れます。

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

difference_.difference(array, other) 
without に似ていますが、 array の中から other に存在しない値のリストを返します。

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

uniq_.uniq(array, [isSorted], [iterator]) エーリアス: unique 
オブジェクト同等性をテストするのに === を使って、 array の重複なし版を返します。  array がソートされていると前もって知っているなら、 isSorted に true を渡すともっと速いアルゴリズムを走らせます。変換に基づいて唯一の項目を計算したいなあら、 iterator 関数を渡してください。

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

zip_.zip(*arrays) 
arrays のそれぞれの中の値を、対応する位置に値が来るように一緒に結合します。配列インデックスが一致するように整理された分離したデータソースを使う時役に立ちます。入れ子の配列の行列を扱っているなら、 zip.apply は似た方法で行列を転置できます。

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

indexOf_.indexOf(array, value, [isSorted]) 
value が array の中で見つかった場所のインデックスか、array の中に現れなかったら-1を返します。ネイティブの indexOf 関数があれば、それを使います。 大きな配列を扱っていて配列が既にソートされていると知っているなら、  isSorted に true を渡してより速い二分木探索を使ってください。

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

lastIndexOf_.lastIndexOf(array, value) 
array の中で value が最後に現れるインデックスか、もし現れなければ  -1 を返します。ネイティブの lastIndexOf 関数があればそれを使います。

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

range_.range([start], stop, [step]) 
each や map ループに重宝する柔軟に番号付けられた整数リストを生成する関数。 start は省略されたらデフォルトは 0 です; step のデフォルトは 。 Returns a list of integers from start から stop まで step ずつ増分(減分)されるの整数のリストを返します。 stop は含みません。

_.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_.bind(function, object, [*arguments]) 
function を object に束縛します。関数が呼ばれたときはいつでも this の値が object になることを意味します。オプションで、引数を事前に埋めるため arguments を function に束縛します。カリー化として知られています。

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

bindAll_.bindAll(object, [*methodNames]) 
methodNames で指定された object 上のメソッドを束縛します。イベントハンドラとして使われる予定の関数を束縛するのにとても重宝します。束縛しないと、あまり役に立たない this とともに呼び出されることになるでしょう。 methodNames が供給されなければオブジェクトの関数プロパティすべべてが束縛されます。

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_.memoize(function, [hashFunction]) 
計算結果をキャッシュすることで与えられた function をメモ化します。遅い計算を高速化するのに役立ちます。オプションの hashFunction を渡すと、元の関数への引数に基づいて結果を保存するハッシュキーを計算するのに使われます。デフォルトの hashFunction はただメモ化された関数への最初の引数をキーとして使います。

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

delay_.delay(function, wait, [*arguments]) 
setTimeou,と同様に wait ミリ秒後に function を呼び出します。 arguments, を渡すと、呼び出す時にそれらを function に転送します。

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

defer_.defer(function) 
setTimeout を遅延 0 で使うのと似ていて、現在のコールスタックがクリアされるまで function の呼び出しを延期します。贅沢な計算を実行したり、UIスレッドを更新からブロックせずにぶつ切りでHTMLレンダリングしたりするのに役立ちます。

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

throttle_.throttle(function, wait) 
関数の減速 (throttled) 版を返します。減速版は、繰り返し呼び出された時、実際にはラップされた関数をせいぜい毎 wait ミリ秒毎に一回呼び出します。ついていけるより早く起こるイベントを律速するのに役立ちます。

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

debounce_.debounce(function, wait) 
デバウンスされた関数をコールすると、最後にその関数を呼び出してから wait ミリ秒経過するまで実行を延期します。入力が途絶えたでだけ起こるべき振る舞いを実装するのに役立ちます。例えば: Markdown コメントのプレビューのレンダリング、ウィンドウがリサイズを止めた後のレイアウトの再計算...

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

once_.once(function) 
一回だけ呼び出せる関数を生成します。修正された関数を繰り返し呼び出しても初回のコールの値を返すだけで効果を持ちません。ブーリアンフラグを設定して後でチェックしなければいけない代わりになり、初期化関数に役に立ちます。 

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

after_.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_.wrap(function, wrapper) 
wrapper 関数に最初の function を最初の引数として渡し、wrapper 関数の内部で function をラップします。これで wrapper が function が動作する前と後でコードを実行したり、引数を調整したり、条件付きで実行したりすることが可能になります。

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

compose_.compose(*functions) 
Returns the composition of a list of functions のリストの合成を返します。合成関数では、それぞれの関数が続く関数の戻り値を使います。数学用語では、関数 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_.keys(object) 
object のプロパティ名すべてを返します。

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

values_.values(object) 
object のプロパティの値すべてを返します。properties.

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

functions_.functions(object) エーリアス: methods 
オブジェクトのすべてのメソッドの名前—言い換えるとオブジェクトのすべての関数プロパティの名前の並び替えられたリストを返します。

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

extend_.extend(destination, *sources) 
source オブジェクトのプロパティすべてを destination オブジェクトにコピーします。順にコピーされるので、最後のソースは前の引数の中の同じ名前のプロパティを上書きします。

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

defaults_.defaults(object, *defaults) 
Fill in missing properties in object の中の欠けているプロパティを defaults オブジェクトからのデフォルト値で埋めます。一旦プロパティが埋められると、次からは defaults は効果を持ちません。

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

clone_.clone(object) 
object. の浅いコピーのクローンを生成します。すべての入れ子のオブジェクトや配列は参照でコピーされて、複製されません。

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

tap_.tap(object, interceptor) 
 object を引数に interceptor を呼び出し、 object を返します。このメソッドの主な目的は、メソッドチェーンの中で中間結果上に演算を実行するために、チェーンの中に「入り込む」ことです。

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

isEqual_.isEqual(object, other) 
2つのオブジェクトの間で最適化された深い比較を実行し、等しいと見なれるべきか決定します。

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(object) 
object が値を含まないなら true を返します。

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

isElement_.isElement(object) 
object が DOM 要素なら true を返します。 

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

isArray_.isArray(object) 
object が配列なら true を返します。

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

isArguments_.isArguments(object) 
object が Arguments オブジェクトなら true を返します。

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

isFunction_.isFunction(object) 
object が関数なら true を返します。

_.isFunction(alert);
=> true

isString_.isString(object) 
object が文字列なら true を返します。

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

isNumber_.isNumber(object) 
object が数なら true を返します。

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

isBoolean_.isBoolean(object) 
object が true か false なら true を返します。

_.isBoolean(null);
=> false

isDate_.isDate(object) 
object が日付なら true を返します。

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

isRegExp_.isRegExp(object) 
object が正規表現なら true を返します。

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

isNaN_.isNaN(object) 
object が NaN なら true を返します。

注意: これはネイティブの isNaN 関数と同じではありません。ネイティブの isNaN 関数は変数が undefined の時も true を返します。

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

isNull_.isNull(object) 
object が null なら true を返します。

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

isUndefined_.isUndefined(variable) 
object が undefined なら true を返します。

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

ユーティリティ関数

noConflict_.noConflict() 
"_" 変数の制御を前の所有者に返します。  Underscore オブジェクトへの参照を返します。

var underscore = _.noConflict();

identity_.identity(value) 
引数と同じものを返します。数学では:  f(x) = x
個の関数は役立たずに見えますが、デフォルトのイテレータとして Underscore の至る所で使われています。

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

times_.times(n, iterator) 
与えられた iterator 関数を n 回呼び出します。

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

mixin_.mixin(object) 
Underscore をあなたのユーティリティ関数で拡張可能にします。{name: function} 定義のハッシュを渡して、OOPラッパはもちろん、 Underscore オブジェクトにあなたの関数を追加してください。

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

uniqueId_.uniqueId([prefix]) 
必要とするクライアント側モデルや DOM 要素用にグローバルに一意のidをを生成します。 prefix を渡すと、 id にそれを追加します。

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

escape_.escape(string) 
&や, <>"',  /文字を置き換えて、HTML への挿入用に文字列をエスケープします。

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

template_.template(templateString, [context]) 
JavaScript テンプレートをレンダリング用に評価可能な関数にコンパイルします。 JSON データソースから少量だけど複雑な HTMLをレンダリングするのに役に立ちます。テンプレート関数は <%= … %> を使って変数を改変することも、<% … %> を使って任意の JavaScript コードを実行することもできます。 値を改変して、それをHTMLエスケープされたものにしたいなら、 <%- … %> を使ってください。テンプレート関数を評価する時、テンプレートの自由変数に対応するプロパティを持つ context オブジェクトを渡してください。 1回限りのものを書いているなら、 テンプレート関数を返す代わりにすぐに描画するために、 template への二番目のパラメータとして context オブジェクトを渡すことができます。

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>"

JavaScript コード内で print も使うことができます。時にはこれは <%= ... %> を使うより便利です。

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

ERB-スタイルの区切り文字が好みじゃなければ、 Underscore のテンプレート設定を変えて補完コードを始めるのに違うシンボルを使うことができます。 挿入する式、評価する式にそれぞれ一致するように interpolate 正規表現、regex, and an (オプションの) evaluate 正規表現を定義してください。 evaluate 正規表現が提供されないなら、テンプレートは値を改変することだけが可能になります。例えば、 Mustache.js スタイルテンプレートを実行するには:

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

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

Chaining

chain_(obj).chain() 
ラップされたオブジェクトを返します。このオブジェクト上でメソッドをコールすると、 value が使われるまでラップされたオブジェクトを返し続けます。 ( もっと現実的な例)

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

value_(obj).value() 
ラップされたオブジェクトの値を取り出します。

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

Links & Suggested Reading

Underscore.lua, どちらの言語でも適用可能な関数の Lua 移植。 OOP-ラップとチェーンを含みます。 GitHubでソースが入手可能。

Underscore.php, どちらの言語でも適用可能な関数の PHP 移植。 OOP-ラップとチェーンを含みます。 GitHubでソースが入手可能。

Underscore-perl, aたくさんの Underscore.js 関数の Perl 移植。 Perl ハッシュと配列に合わせたもの。 GitHubで入手可能

Underscore.string, 以下の文字列操作用関数を追加した Underscore 拡張: trimstartsWithcontainscapitalizereversesprintf, などなど。

Ruby の Enumerable モジュール。

Prototype.js, Ruby の Enumerable に最も近い方法で JavaScript にコレクション関数を提供します。

Oliver Steele の Functional JavaScript, 文字列ラムダはもちろん、包括的な高階関数サポートを含みます。

Michael Aufreiter の Data.js, JavaScript 用のデータ操作 + 永続ライブラリ

Python の itertools

Change Log

1.2.2 — Nov. 14, 2011

  • Continued tweaks to _.isEqual semantics. Now JS primitives are considered equivalent to their wrapped versions, and arrays are compared by their numeric properties only (#351).
  • _.escape no longer tries to be smart about not double-escaping already-escaped HTML entities. Now it just escapes regardless (#350).
  • In _.template, you may now leave semicolons out of evaluated statements if you wish: <% }) %> (#369).
  • _.after(callback, 0) will now trigger the callback immediately, making "after" easier to use with asynchronous APIs (#366).

1.2.1 — Oct. 24, 2011

  • Several important bug fixes for _.isEqual, which should now do better on mutated Arrays, and on non-Array objects with length properties.(#329)
  • jrburke contributed Underscore exporting for AMD module loaders, and tonylukasavage for Appcelerator Titanium. (#335, #338)
  • You can now _.groupBy(list, 'property') as a shortcut for grouping values by a particular common property.
  • _.throttle'd functions now fire immediately upon invocation, and are rate-limited thereafter (#170, #266).
  • Most of the _.is[Type] checks no longer ducktype.
  • The _.bind function now also works on constructors, a-la ES5 ... but you would never want to use _.bind on a constructor function.
  • _.clone no longer wraps non-object types in Objects.
  • _.find and _.filter are now the preferred names for _.detect and_.select.

1.2.0 — Oct. 5, 2011

  • The _.isEqual function now supports true deep equality comparisons, with checks for cyclic structures, thanks to Kit Cambridge.
  • Underscore templates now support HTML escaping interpolations, using <%- ... %> syntax.
  • Ryan Tenney contributed _.shuffle, which uses a modified Fisher-Yates to give you a shuffled copy of an array.
  • _.uniq can now be passed an optional iterator, to determine by what criteria an object should be considered unique.
  • _.last now takes an optional argument which will return the last N elements of the list.
  • A new _.initial function was added, as a mirror of _.rest, which returns all the initial values of a list (except the last N).

1.1.7 — July 13, 2011
Added _.groupBy, which aggregates a collection into groups of like items. Added _.union and _.difference, to complement the (re-named)_.intersection. Various improvements for support of sparse arrays. _.toArraynow returns a clone, if directly passed an array. _.functions now also returns the names of functions that are present in the prototype chain.

1.1.6 — April 18, 2011
Added _.after, which will return a function that only runs after first being called a specified number of times. _.invoke can now take a direct function reference. _.every now requires an iterator function to be passed, which mirrors the ECMA5 API. _.extend no longer copies keys when the value is undefined. _.bind now errors when trying to bind an undefined value.

1.1.5 — Mar 20, 2011
Added an _.defaults function, for use merging together JS objects representing default options. Added an _.once function, for manufacturing functions that should only ever execute a single time. _.bind now delegates to the native ECMAScript 5 version, where available. _.keys now throws an error when used on non-Object values, as in ECMAScript 5. Fixed a bug with_.keys when used over sparse arrays.

1.1.4 — Jan 9, 2011
Improved compliance with ES5's Array methods when passing null as a value. _.wrap now correctly sets this for the wrapped function. _.indexOf now takes an optional flag for finding the insertion index in an array that is guaranteed to already be sorted. Avoiding the use of .callee, to allow_.isArray to work properly in ES5's strict mode.

1.1.3 — Dec 1, 2010
In CommonJS, Underscore may now be required with just: 
var _ = require("underscore"). Added _.throttle and _.debounce functions. Removed _.breakLoop, in favor of an ECMA5-style un-break-able each implementation — this removes the try/catch, and you'll now have better stack traces for exceptions that are thrown within an Underscore iterator. Improved the isType family of functions for better interoperability with Internet Explorer host objects. _.template now correctly escapes backslashes in templates. Improved _.reduce compatibility with the ECMA5 version: if you don't pass an initial value, the first item in the collection is used. _.eachno longer returns the iterated collection, for improved consistency with ES5'sforEach.

1.1.2
Fixed _.contains, which was mistakenly pointing at _.intersect instead of_.include, like it should have been. Added _.unique as an alias for _.uniq.

1.1.1
Improved the speed of _.template, and its handling of multiline interpolations. Ryan Tenney contributed optimizations to many Underscore functions. An annotated version of the source code is now available.

1.1.0
The method signature of _.reduce has been changed to match the ECMAScript 5 signature, instead of the Ruby/Prototype.js version. This is a backwards-incompatible change. _.template may now be called with no arguments, and preserves whitespace. _.contains is a new alias for _.include.

1.0.4
Andri Möll contributed the _.memoize function, which can be used to speed up expensive repeated computations by caching the results.

1.0.3
Patch that makes _.isEqual return false if any property of the compared object has a NaN value. Technically the correct thing to do, but of questionable semantics. Watch out for NaN comparisons.

1.0.2
Fixes _.isArguments in recent versions of Opera, which have arguments objects as real Arrays.

1.0.1
Bugfix for _.isEqual, when comparing two objects with the same number of undefined keys, but with different names.

1.0.0
Things have been stable for many months now, so Underscore is now considered to be out of beta, at 1.0. Improvements since 0.6 include_.isBoolean, and the ability to have _.extend take multiple source objects.

0.6.0
Major release. Incorporates a number of Mile Frawley's refactors for safer duck-typing on collection functions, and cleaner internals. A new _.mixinmethod that allows you to extend Underscore with utility functions of your own. Added _.times, which works the same as in Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray, and Object.keys.

0.5.8
Fixed Underscore's collection functions to work on NodeLists andHTMLCollections once more, thanks to Justin Tulloss.

0.5.7
A safer implementation of _.isArguments, and a faster _.isNumber,
thanks to Jed Schmidt.

0.5.6
Customizable delimiters for _.template, contributed by Noah Sloan.

0.5.5
Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object.

0.5.4
Fix for multiple single quotes within a template string for _.template. See:Rick Strahl's blog post.

0.5.2
New implementations of isArrayisDateisFunctionisNumberisRegExp, andisString, thanks to a suggestion from Robert Kieffer. Instead of doingObject#toString comparisons, they now check for expected properties, which is less safe, but more than an order of magnitude faster. Most other Underscore functions saw minor speed improvements as a result. Evgeniy Dolzhenko contributed _.tapsimilar to Ruby 1.9's, which is handy for injecting side effects (like logging) into chained calls.

0.5.1
Added an _.isArguments function. Lots of little safety checks and optimizations contributed by Noah Sloan and Andri Möll.

0.5.0
[API Changes] _.bindAll now takes the context object as its first parameter. If no method names are passed, all of the context object's methods are bound to it, enabling chaining and easier binding. _.functions now takes a single argument and returns the names of its Function properties. Calling_.functions(_) will get you the previous behavior. Added _.isRegExp so thatisEqual can now test for RegExp equality. All of the "is" functions have been shrunk down into a single definition. Karl Guertin contributed patches.

0.4.7
Added isDateisNaN, and isNull, for completeness. Optimizations for isEqualwhen checking equality between Arrays or Dates. _.keys is now 25%–2X faster (depending on your browser) which speeds up the functions that rely on it, such as _.each.

0.4.6
Added the range function, a port of the Python function of the same name, for generating flexibly-numbered lists of integers. Original patch contributed byKirill Ishanov.

0.4.5
Added rest for Arrays and arguments objects, and aliased first as head, andrest as tail, thanks to Luke Sutton's patches. Added tests ensuring that all Underscore Array functions also work on arguments objects.

0.4.4
Added isString, and isNumber, for consistency. Fixed _.isEqual(NaN, NaN) to return true (which is debatable).

0.4.3
Started using the native StopIteration object in browsers that support it. Fixed Underscore setup for CommonJS environments.

0.4.2
Renamed the unwrapping function to value, for clarity.

0.4.1
Chained Underscore objects now support the Array prototype methods, so that you can perform the full range of operations on a wrapped array without having to break your chain. Added a breakLoop method to break in the middle of any Underscore iteration. Added an isEmpty function that works on arrays and objects.

0.4.0
All Underscore functions can now be called in an object-oriented style, like so: _([1, 2, 3]).map(...);. Original patch provided by Marc-André Cournoyer. Wrapped objects can be chained through multiple method invocations. A functions method was added, providing a sorted list of all the functions in Underscore.

0.3.3
Added the JavaScript 1.8 function reduceRight. Aliased it as foldr, and aliasedreduce as foldl.

0.3.2
Now runs on stock Rhino interpreters with: load("underscore.js"). Addedidentity as a utility function.

0.3.1
All iterators are now passed in the original collection as their third argument, the same as JavaScript 1.6's forEach. Iterating over objects is now called with(value, key, collection), for details see _.each.

0.3.0
Added Dmitry Baranovskiy's comprehensive optimizations, merged in Kris Kowal's patches to make Underscore CommonJS and Narwhal compliant.

0.2.0
Added compose and lastIndexOf, renamed inject to reduce, added aliases forinjectfiltereverysome, and forEach.

0.1.1
Added noConflict, so that the "Underscore" object can be assigned to other variables.

0.1.0
Initial release of Underscore.js.

A DocumentCloud Project

Comments