Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
書籍転載:JavaScriptライブラリ実践活用[厳選111]

書籍転載:JavaScriptライブラリ実践活用[厳選111]

[Underscore.js]さなざまなコレクション操作を行う

2013年6月6日

書籍転載の9本目(書籍内の番号は「100」)。ユーティリティ・ライブラリ「Underscore.js」の基礎として、さまざまなコレクション操作する方法を説明。

WINGSプロジェクト 高野 将
  • このエントリーをはてなブックマークに追加

書籍転載について

 本コーナーは、技術評論社発行の書籍『JavaScriptライブラリ実践活用[厳選111]』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。

 『JavaScriptライブラリ実践活用[厳選111]』の詳細や購入は技術評論社のサイト目次ページをご覧ください。

ご注意

本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。

Underscore.jsは多くの機能を持つユーティリティライブラリです。コレクション操作用のAPIを使うことで、さまざまなコレクション操作が簡単に行えるようになります。

  • 名称: Underscore.js
  • 分類: フレームワーク
  • URL: http://underscorejs.org/
  • 関連ファイル: underscore-1.4.3.js
図100-01 Underscore.jsのコレクションAPI実行イメージ
図100-01 Underscore.jsのコレクションAPI実行イメージ

コレクション操作API

 Underscore.jsは_.method()のような、_(アンダースコア)グローバル変数にさまざまな便利機能を行うメソッドを追加するライブラリです。この中に含まれるコレクション操作APIを使うと、コレクションに対してさまざまな操作を行えます。主なメソッドを表100-01に示します。その中で、主なものをサンプルコードとともに紹介しましょう。

メソッド説明
each(obj, iterator) objコレクションの各項目に対して、iterator関数の処理を行う
map(obj, iterator) objコレクションの各項目に対する、iterator関数による射影を返す
reduce(obj, iterator, memo) objコレクションの先頭から、itarator関数を使用した畳み込み計算を行った結果を返す。memoには初期値を設定する
filter(obj, iterator) objコレクションの各項目の内、iterator関数で指定した条件に合致する項目のみに絞り込んだ新たなコレクションを返す
chain(obj) objコレクションに対する操作メソッドを、メソッドチェーンでつなげて書けるようにする。chainメソッドの後に繋げるメソッドでは、obj引数を省略できる
表100-01 Underscore.jsの主なコレクション操作API

 まず、Underscore.jsを使うにはリスト100-01のようにインポートします。依存しているライブラリはありませんので、これで使用する準備は完了です。

HTML
<!-- Underscore.jsをインポート -->
<script type="text/javascript" src="js/underscore-1.4.3.js"></script>
リスト100-01 Underscore.jsの準備(underscore.js-1.collection.html)より抜粋

 次に表100-01に示したメソッドの具体的な使い方を説明しましょう。リスト100-02を見てください。

JavaScript
// 1 eachメソッド
function doEach() {
  var source = ["太郎", "二郎", "三郎"];
  _.each(source, function (x) { $("#each").append($("<li>").text(x)); });
}

// 2 mapメソッド
function doMap() {
  var source = ["太郎", "二郎", "三郎"];
  var results = _.map(source, function (x) { return "Hello " + x + "!"; });
  for (var key in results) {
    $("#map").append($("<li>").text(results[key]));
  }
}

// 3 reduceメソッド
function doReduce() {
  var source = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  var sum = _.reduce(source, function (x, y) { return x + y }, 0);
  $("#reduce").text(sum);
}

// 4 filterメソッド
function doFilter() {
  var source = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  var results = _.filter(source, function (x) { return x % 2 == 0; })
  for (var key in results) {
    $("#filter").append($("<li>").text(results[key]));
  }
}

// 5 chainメソッド
function doChain() {
  var source = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  _.chain(source)
    .filter(function (x) { return x % 2 != 0; })
    .map(function (x) { return "Odd number " + x; })
    .each(function (x) { $("#chain").append($("<li>").text(x)); });
}
リスト100-02 コレクション操作API使用例(underscore-sample.js)
図100-02 サンプル実行結果画面
図100-02 サンプル実行結果画面

1 eachメソッド

 コレクションの要素の列挙を行い、要素ごとに処理を行います。引数には処理対象コレクションオブジェクト、要素ごとに行いたい処理を定義した関数を指定します。

 関数の引数にはコレクションの要素が渡されますので、その要素を使って処理を行います。サンプルでは、コレクションの要素をもとに、HTMLの項目に要素を追加しています(図100-02[1])。

2 mapメソッド

 コレクションの射影を取得します。射影とはそれぞれの要素に指定した変換処理を行い、その結果をコレクションとして取得する操作です。引数には処理対象コレクションオブジェクト、射影操作を定義した関数を指定します。

 関数の引数にはコレクションの要素が渡されますので、その要素を元に変換処理を行います。その変換した値で構成されるコレクションが、戻り値として戻されます。

 サンプルでは、コレクションの要素を使って「Hello name!」形式の文字列に変換しています(図100-02[2])。

3 reduceメソッド

 コレクションの各要素の畳み込み処理を行います。畳み込み処理とは、サンプルのように全要素の合計を集計したりするための処理です。

 その動作は要素の先頭から処理を開始し、まずは1+2=3の計算を行います。次にこの計算結果を使って、(1+2)+3=3+3=6、((1+2)+3)+4=(3+3)+4=6+4=10、といったように全要素に対して順番に計算を行っていきます。

 引数には処理対象コレクションオブジェクト、畳み込み処理を定義した関数、最初の要素と処理を行う際の初期値(サンプルでいえば、x+1=nと計算するためのxの値)を指定します。

 関数の引数にはそれまでの演算結果、次の要素の値の2つの引数が渡されますので、これらを使った演算処理を行います。そして、最終的な演算結果が戻り値として返されます。

 サンプルでは、総和を求めるために、2つの引数を足し合わせる処理を行っています(図100-02[3])。

4 filterメソッド

 コレクションの要素の絞り込みを行います。引数には処理対象コレクションオブジェクト、絞り込み条件を表す関数を指定します。

 関数の引数にはコレクションの要素が渡されますので、その要素を使って、絞り込みたい要素の時にtrueを返します。すると、絞り込まれた要素で構成される新しいコレクションが、戻り値として返されます。

 サンプルでは、数値のコレクションのうち、偶数(=2で割り切れるもの)のみ抽出しています(図100-02[4])。

5 chainメソッド

 これまで紹介したような各コレクション処理を組み合わせて使いたい場合もあります。そんな時、chainメソッドを使うことで、各処理をメソッドチェーンでつなげて記述できるようになります。

 引数には起点となる処理対象コレクションオブジェクトを指定し、あとは各コレクション操作をつなげていきます。この時のポイントは、それぞれのコレクション操作メソッドの引数に処理対象コレクションオブジェクトが不要になっていることです。

 サンプルでは、数字のコレクションのうち奇数のものをfilterメソッドで絞り込み、mapメソッドで「Odd number n」形式に変換し、eachメソッドでHTMLの項目への要素追加、という一連の流れをメソッドチェーンで指定しています(図100-02[5])。

※以下では、本稿の前後を合わせて5回分(第7回~第11回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

書籍転載:JavaScriptライブラリ実践活用[厳選111]
7. [Knockout]MVVMパターンでアプリケーションを構築する

書籍転載の7本目(書籍内の番号は「89」)。MVVM(Model-View-ViewModel)パターンをサポートするJavaScriptライブラリである「Knockout」の基礎と、基本的な使い方を解説。

書籍転載:JavaScriptライブラリ実践活用[厳選111]
8. [QUnit]テストコードを実行し、ブラウザで結果を確認する

書籍転載の8本目(書籍内の番号は「111」)。JavaScript用テストランナーの定番ライブラリである「QUnit」の基礎と基本的な使い方を説明。

書籍転載:JavaScriptライブラリ実践活用[厳選111]
9. 【現在、表示中】≫ [Underscore.js]さなざまなコレクション操作を行う

書籍転載の9本目(書籍内の番号は「100」)。ユーティリティ・ライブラリ「Underscore.js」の基礎として、さまざまなコレクション操作する方法を説明。

書籍転載:JavaScriptライブラリ実践活用[厳選111]
10. [Underscore.js]テンプレートとオブジェクトから文字列を生成する

書籍転載の10本目(書籍内の番号は「101」)。テンプレートとオブジェクトをバインドし、その結果を出力できる「Underscore.js」のテンプレートAPIの使い方を説明。

書籍転載:JavaScriptライブラリ実践活用[厳選111]
11. RSpec風の構文でBDD用のテスト・コードを記述する[Jasmine]

書籍転載の11本目(書籍内の番号は「108」)。RSpec風のテスト・コードが書けるBDD(ビヘイビア駆動開発)テスティング・フレームワーク「Jasmine」の基本的な使い方を説明する。

サイトからのお知らせ

Twitterでつぶやこう!