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