Hatena::ブログ(Diary)

Remaki*

2007-03-31

[] prototype.jsを読む(5)


Object.extend(Number.prototype, {
  toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },

  succ: function() {
    return this + 1;
  },

  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  }
});

Numberのprototype関数を追加。最後のtimesで$Rとeachが登場。これは何だろう?

var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

ObjectRangeオブジェクトを返す関数。つまりnew ObjectRange(...)を短く$R(...)と書くためのもの。で、ObjectRangeって何?

ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

ObjectRangeはEnumerableを継承したクラス。今回使われているeachはEnumerableで宣言されている。

each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          if (e != $continue) throw e;
        }
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  },

ややこしい!eachの中で内部的に_eachが使われている。書き換えよう。

each : function(iterator) {
var index = 0;
    try {
        var value = this.start;
        while (this.include(value)) {
            try {
                iterator(value, index++);
            }
            catch(e) {
                if(e != $continue) throw e;
            }
            value = value.succ();
        }
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  },

includeは値がObjectRangeオブジェクトを作るときに指定した範囲に含まれているかをチェックする関数。trueかfalseかでexclusiveを範囲に含めるかどうか決める。で、全体としてはvalueが範囲に含まれている限りiterator処理を繰り返す。valueはsuccしてカウントアップしていく。したがってtimes関数はおそらく

10.times(sayHello);

のように使われる。

times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
}

というわけで見ての通り、0からthis、つまりtimesを呼び出した数値になるまでiterator処理を繰り返すのがこのtimes関数。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/remaki/20070331/1175346140