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); }
//覆盖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
//终于看到this._each了,现在明白为什么ObjectRange里面会重写了_each方法了吧。在遍历的时候要用到这个方法 function each(iterator, context) { var index = 0; try { this._each(function(value) { iterator.call(context, value, index++); }); } catch (e) { if (e != $break) throw e; } return this; }
//======> this._each()
//详细说明一下this._each() //关键就是succ()这个方法,因为_each里面使用这个方法产生下一个数值。 //这个succ()在哪里呢?在Number.prototype和String.prototype里面定义了这个方法 function _each(iterator) { var value = this.start; while (this.include(value)) { iterator(value); value = value.succ(); } }