定义
迭代器模式是指提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。
作用
遍历一个聚合对象,这是迭代器模式的作用。
举例
该模式的例子就数不胜数了。数组遍历方法比如Array.prototype.forEach、jQuery中的$.each()等等都是迭代器。下面自己来实现一个each函数,第一个参数是数组,第二个参数是每一步的处理函数
var each = function (arr, callback) { for (var i = 0, l = arr.length; i < l; i++) { callback.call(arr[i], i, arr[i]); }}// testeach([1,2,3], function (i ,n) { alert([i, n]);});复制代码
迭代器可以分为内部迭代器和外部迭代器。上面的each函数属于内部迭代器,each函数的内部已经定义好了迭代规则,完全接手了整个过程,外部只需要调用一次。内部迭代器使用起来非常方便,就调一个函数即可,这是内部迭代器的优点。但是它只能迭代一个数组,要想迭代两个数组必须改变内部函数的实现,违反了开放-封闭原则。
而外部迭代器则必须显式的请求迭代下一个元素。外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,因为我们可以手动地控制整个迭代过程。
面试题:实现一个函数,第一次执行返回1,第二次执行返回2......这就是一个外部迭代器的案例,这道面试题也经常遇到,上菜:
var iterator = function () { var count = 1; return function () { console.log(count++); }}// testvar output = iterator();output(); // 1output(); // 2output(); // 3......复制代码
下面实现一个较完整的迭代器:
var Iterator = function (obj) { var current = 0; var next = function () { current += 1; }; var isDone = function () { return current >= obj.length; }; var getCurrItem = function () { return obj[current]; }; return { next: next, isDone: isDone, getCurrItem: getCurrItem, length: obj.length };}复制代码
从上面的迭代器实现可以看出,只要被迭代的聚合对象拥有length属性而且可以用下标访问,那么它就是迭代器。Javascript中的类数组对象也是迭代器。
倒序迭代器
顾名思义,倒序迭代器就是以倒序的方式去访问数组的每一个对象:
var reverseEach = function (arr, callback) { for (var l = arr.length; l >= 0; l--) { callback(l, arr[l]); }}// testreverseEach([0, 1, 2], function (i ,n) { console.log(n);})复制代码
中止迭代器
var each = function (arr, callback) { for (var i = 0, l = arr.length; i < l; i++) { if (callback(i, arr[i]) === false){ break; } }}// testeach([1,2,3,4,5], function (i, n) { if (n > 3) { return false; } console.log(n);});复制代码
优点
1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
小结
迭代器模式是一种相对简单的模式,绝大语言也内置了迭代器。