GANCHIKU.com

for文書きたくない。

タイトルにYUIとか書くと全く関係ないところが、キーワードを拾って、リンクを張ってきやがる。日本人にとって、YUIという言葉は、普通Yahoo! User Interfaceなんかではなく、人の名前になる。しかも、女性の可能性が高いので、リファラーがYUIだらけに。

というわけで、YUIを最近使っているわけだが、イテレートするのにfor文を書くのが嫌なので、eachとmapだけでも、prototype.jsから移植してみた。勝手に、YAHOO.util.Collectionと名前を付けてみたりw。改め、YAHOO.utilx.Collectionにした。また、使いそうなコレクションがあったら追加してみる予定。別に、anyやらallやら全部prototype.jsから持ってきてもいいのだけど、面倒なので必要があれば実装するし、使わなければ実装しない。
というわけで、以下がソース

YAHOO.namespace('utilx');
YAHOO.utilx.Collection = function() {
  var _each = function(data, iterator) {
    if (YAHOO.lang.isArray(data)) {
      for (var i = 0, l = data.length; i < l; i++) {
        iterator(data[i]);
      }
    } else if (data && typeof data === 'object') {
      for (var property in data) {
        iterator({key: property, value:data[property]});
      }
    }
  };
  return {
    $break: {},
    $continue: new Error('"throw $continue" is deprecated, use "return" instead'),
    each: function(data, iterator) {
      var index = 0;
      try {
        _each(data, function(value) {
          iterator(value, index++);
        });
      } catch (e) {
        if (e != this.$break) throw e;
      }
      return data;
    },
    map: function(data, iterator) {
      var results;
      this.each(data, function(value, index) {
        var result = (iterator || function(v) { return v;})(value, index);
        if (YAHOO.lang.isArray(data)) {
          results = results || [];
          results.push(result);
        } else {
          results = results || {};
          if (result && result['key'] && result['value']) {
            results[result['key']] = result['value'];
          }
        }
      });
      return results;
    }
  }
}();

次のように使う。配列のとき

var hogeArray = ["foo", "bar", "baz"];
YAHOO.utilx.Collection.each(hogeArray, function(data) {
    console.log(data + "hogehoge")
});
hogeArray = YAHOO.utilx.Collection.map(hogeArray, function(data) {
  if (data == 'baz') {
    throw YAHOO.utilx.Collection.$break;
  }
  data = data + "hogehoge";
  return data;
});
console.log(hogeArray);

オブジェクトのとき

var hogeObj = {"foo": "This is Foo", "bar": "This is Bar", "baz": "This is Baz"};
YAHOO.utilx.Collection.each(hogeObj, function(data) {
    console.log(data.value + "hogehoge")
});
hogeObj = YAHOO.utilx.Collection.map(hogeObj, function(data) {
  if (data.key == 'baz') {
    throw YAHOO.utilx.Collection.$break;
  }
  data.value = data.value + "hogehoge";
  return data;
});
console.log(hogeObj);

とりあえず、for文を書きたくないので、これで少しすっきりした。


よくよく考えれば、このような何度も使う可能性のあるメソッド等はprototypeオブジェクトに持たせるのがいいような気がしてきた。prototypeオブジェクトは、このために使うのが良さそうだな。それから、YAHOO.util改め、YAHOO.utilxにした。さすがにutilのnamespaceを汚すのは良くないからね。

Shin Ohno 2003-2012