prototype.jsを読み解く

第3回 Prototypeライブラリ(640~931行目)

この記事を読むのに必要な時間:およそ 10.5 分

ObjectRangeクラス

0902: ObjectRange = Class.create();
0903: Object.extend(ObjectRange.prototype, Enumerable);

902行目からはObjectRangeクラスです。

まずはClass.create()で雛形をつくり,EnumerableをObjectRange.prototypeにmixinしています。

0904: Object.extend(ObjectRange.prototype, {
0905:   initialize: function(start, end, exclusive) {
0906:     this.start = start;
0907:     this.end = end;
0908:     this.exclusive = exclusive;
0909:   },
0910: 

コンストラクタでは,単にインスタンス変数に引数を保存しているだけです。また,このコンストラクタは後述する$Rショートカット関数と同じインターフェイスを持っています。

0911:   _each: function(iterator) {
0912:     var value = this.start;
0913:     while (this.include(value)) {
0914:       iterator(value);
0915:       value = value.succ();
0916:     }
0917:   },
0918: 

Enumerable.each()から呼び出される_each()メソッドです。

ObjectRangeオブジェクトは,範囲が大きかろうとすべての値を配列で持っているわけではなく,先頭と終了,境界値を含むかどうかのフラグ,しか持っていません。

そのため,_each()内のwhileループでは,this.startから開始して,それが範囲内に含まれているかどうかをthis.include()でチェックして,含まれていればイテレータ関数を呼び出して次の値をthis.succ()で取得する,という形になっています。

0919:   include: function(value) {
0920:     if (value < this.start)
0921:       return false;
0922:     if (this.exclusive)
0923:       return value < this.end;
0924:     return value <= this.end;
0925:   }
0926: });
0927: 

919行目からはinclude()メソッドです。

最初はthis.start未満だったら偽を返します。

this.exclusiveが真の場合,this.endが示す値はObjectRangeの範囲に含まれません。そのため 923行目では渡された値がthis.end未満なら真,そうでなければ偽を返しています。

this.exclusiveが偽の場合,this.end以下なら真,そうでなければ偽を返します。

0928: var $R = function(start, end, exclusive) {
0929:   return new ObjectRange(start, end, exclusive);
0930: }
0931: 

928行目からは$R()ショートカット関数です。

単にnewでObjectRangeインスタンスを作成し,返しているだけです。

著者プロフィール

栗山淳(くりやまじゅん)

S2ファクトリー株式会社株式会社イメージソース所属。
本業はWeb制作会社の裏方。得意分野はFreeBSDやPerlのはずだが,必要に迫られるとHTML/CSSやJavaScriptも書く。