チェ・ゲバムラの日記

脱犬の道を目指す男のブログ

【JS】vol. 2/3 データ検索(Underscore.jsライブラリの便利なメソッド)〜Chapter4 ブレイクスルーJavaScript フロントエンジニアとして越えるべき5つの壁〜

Underscore.jsとは

配列を扱う上で役立つライブラリ。
JavaScriptは多言語に比べて配列操作に弱いので補完してくれる。
プロトタイプ汚染もなく、map,filter,invoke,bindAllなど便利な関数が100以上用意されている。

mapメソッド

引数として与えられた関数を書く配列要素に対して実行し、
その結果から新しい配列を生成する。
例:複数のオブジェクトが入った配列の中から、あるkeyのvalueを集めたい場合に便利。

var stooges = [ 
  {
    name:"curly",
    age:25
  },{ 
    name:"moe",
    age:21
  },{ 
    name:"larry",
    age:23
  }
];

_.map(stooges, function(e){
  return e.name;
});

結果
["curly", "moe", "larry"]


filterメソッド

引数で与えられた関数を各配列要素に対して実行し、合格したものだけを抽出した新しい配列を生成する。
n以上またはn以下のものを抽出したい場合に便利。

_.filter([12,5,8,130,44], function(e){
  return e >= 10;
});

結果[12,130,44]

reduceメソッド

引数で与えられた関数を書く配列要素に対して(左から右へ)実行。
その際に直前の配列要素で処理した返り値を受け取る。
配列の全ての和を求めたい時に便利。

_.reduce([0,1,2,3] , function(prev, current) {
  return prev + current;
});

結果
6

invokeメソッド

配列の各要素に対して、引数に指定した関数名を実行する。
sortしたいだけなど、目的がはっきりしている時に便利。

_.invoke([5,1,7], ["Carol","Alice", "Bob"]], "sort");

結果
[[1,5,7],["Alice","Bob","Carol"]]

bindAllメソッド

オブジェクトを関数にバインドする。
関数が呼ばれた時にthisが参照する値をobjectの値にすることができる。
例:clickイベントを登録する時、thisの参照する値をobjectにする

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

_.bindAll(buttonView, "onClick","onHover");

$("#underscore_button").on("click", buttonView.onClick);

結果
clicked: underscore

データ検索を実装する

  function App(url) {
    this.bindEvents();
    var self = this;
    this.fetch(url).then(function(data) {
      self.data = data;
    }, function(e) {
      console.error("データの取得に失敗しました");
    });
  }

  App.prototype.bindEvents = function() {
    _.bindAll(this, "onChange");
    $("select").on("change", this.onChange);
  };

  App.prototype.fetch = function(url) {
    return $.ajax({
      url: url,
      dataType: "json"
    });
  };

  App.prototype.onChange = function(e) {
    var self = this;
    var where = $("select").map(function(i, el) {
      var $el = $(el);
      return function(list) {
        return self[$el.attr("name")](list, $el.val());
      };
    });
    var list = _.reduce(where, function(prev, current) {
      return current(prev);
    }, this.data.list);
  };

  App.prototype.sort = function(list, key) {
    if (this.isEmpty(key)) {
      return list;
    }
    return _.sortBy(list, function(e) {
      return e[key];
    });
  };

  App.prototype.filter = function(list, value) {
    if (this.isEmpty(value)) {
      return list;
    }
    return _.filter(list, function(e) {
      return e["group"] === value;
    });
  };

  App.prototype.isEmpty = function(value) {
    return value === "";
  };

new App("data.json");


※onChangeとは、フォーム内のエレメント(要素)の内容が変更された時に起こるイベント処理の事