November 16, 2007

for文書きたくない。

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

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

  1. YAHOO.namespace('utilx');
  2. YAHOO.utilx.Collection = function() {
  3.   var _each = function(data, iterator) {
  4.     if (YAHOO.lang.isArray(data)) {
  5.       for (var i = 0, l = data.length; i <l; i++) {
  6.         iterator(data[i]);
  7.       }
  8.     } else if (data && typeof data === 'object') {
  9.       for (var property in data) {
  10.         iterator({key: property, value:data[property]});
  11.       }
  12.     }
  13.   };
  14.   return {
  15.     $break: {},
  16.     $continue: new Error('"throw $continue" is deprecated, use "return" instead'),
  17.     each: function(data, iterator) {
  18.       var index = 0;
  19.       try {
  20.         _each(data, function(value) {
  21.           iterator(value, index++);
  22.         });
  23.       } catch (e) {
  24.         if (e != this.$break) throw e;
  25.       }
  26.       return data;
  27.     },
  28.     map: function(data, iterator) {
  29.       var results;
  30.       this.each(data, function(value, index) {
  31.         var result = (iterator || function(v) { return v;})(value, index);
  32.         if (YAHOO.lang.isArray(data)) {
  33.           results = results || [];
  34.           results.push(result);
  35.         } else {
  36.           results = results || {};
  37.           if (result && result['key'] && result['value']) {
  38.             results[result['key']] = result['value'];
  39.           }
  40.         }
  41.       });
  42.       return results;
  43.     }
  44.   }
  45. }();

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

  1. var hogeArray = ["foo", "bar", "baz"];
  2. YAHOO.utilx.Collection.each(hogeArray, function(data) {
  3.     console.log(data + "hogehoge")
  4. });
  5. hogeArray = YAHOO.utilx.Collection.map(hogeArray, function(data) {
  6.   if (data == 'baz') {
  7.     throw YAHOO.utilx.Collection.$break;
  8.   }
  9.   data = data + "hogehoge";
  10.   return data;
  11. });
  12. console.log(hogeArray);

オブジェクトのとき

  1. var hogeObj = {"foo": "This is Foo", "bar": "This is Bar", "baz": "This is Baz"};
  2. YAHOO.utilx.Collection.each(hogeObj, function(data) {
  3.     console.log(data.value + "hogehoge")
  4. });
  5. hogeObj = YAHOO.utilx.Collection.map(hogeObj, function(data) {
  6.   if (data.key == 'baz') {
  7.     throw YAHOO.utilx.Collection.$break;
  8.   }
  9.   data.value = data.value + "hogehoge";
  10.   return data;
  11. });
  12. console.log(hogeObj);

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


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

Leave a comment

Bloglines feedburner