Ranges represent an interval of values. The value type just needs to be “compatible,” that is, to implement a succ method letting us step from one value to the next (its successor).
Prototype provides such a method for Number and String, but you are of course welcome to implement useful semantics in your own objects, in order to enable ranges based on them.
ObjectRange對象基本就是實現了連續的數字或者字符串,其中只包含一個方法,include,判斷某個數字或者字符串是否在ObjectRange里。并且ObjectRange對象還混入了Enumerable的方法,所以可以直接在ObjectRange對象上調用Enumerable對象里面的方法。
代碼如下:
//創建ObjectRange的便捷方法
function $R(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
}
//創建ObjectRange對象并且繼承自Enumerable
var ObjectRange = Class.create(Enumerable, (function() {
//初始化方法,exclusive為true時,不包含end數值,默認為undefined也就相當于false
function initialize(start, end, exclusive) {
this.start = start;
this.end = end;
this.exclusive = exclusive;
}
//覆蓋Enumerable里面的_each方法,在遍歷ObjectRange對象時需要用到此方法
function _each(iterator) {
var value = this.start;
while (this.include(value)) {
iterator(value);
value = value.succ();
}
}
//判斷某個數值或者字符串是否包含在ObjectRange對象里
function include(value) {
if (value < this.start)
return false;
if (this.exclusive)
return value < this.end;
return value <= this.end;
}
return {
initialize: initialize,
_each: _each,
include: include
};
})());
看一下示例,然后在詳細解釋一些細節:
代碼如下:
$A($R('a', 'e'))
// -> ['a', 'b', 'c', 'd', 'e'], no surprise there
//千萬不要嘗試輸出下面返回的結果,否者將會造成瀏覽器直接死掉
$A($R('ax', 'ba'))
// -> Ouch! Humongous array, starting as ['ax', 'ay', 'az', 'a{', 'a|', 'a}', 'a~'...]
這里說一下$A($R('a', 'e')),如何返回值。首先看$A方法,前面的文章【Prototype 學習——工具函數學習($A方法)】中已經詳細講解了$A方法,不知道請自行參考。在$A方法里面有這樣一句:if ('toArray' in Object(iterable)) return iterable.toArray();我們知道,ObjectRange里面混入了Enumerable里面的方法,也就是說間接實現了toArray方法,那么看一下Enumerable里面的toArray方法:
代碼如下:
function toArray() {
return this.map();
}
//======> this.map()
//我們注意到在返回的時候map方法被映射到了collect方法
return {
//...
collect: collect,
map: collect,
//...
}
//======> collect()
//在本例中這個方法其實就相當于返回一個數組,因為傳進來的參數都是undefined。這里面有一個this.each方法,繼續查看