本文由我们团队肖建朋总结
定义
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
迭代器模式属于行为型模式。
意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
主要解决:不同的方式来遍历整个整合对象。
何时使用:遍历一个聚合对象。
如何解决:把在元素之间游走的责任交给迭代器,而不是聚合对象。
迭代器分为内部迭代器和外部迭代器
内部迭代器
内部迭代器是指在迭代器内部已经定义了迭代规则,在使用时,外部只需一次初始调用,不用关心迭代器内部的实现。
下面我们来实现一个内部迭代器:
var inEach = function (ary, callback) {
for(var i = 0; i< ary.length; i++) {
callback(i, ary[i])
}
}
inEach([1,2,3,4], function(i, item){
console.log(i, item) //
})
inEach函数对于外部来说,只需调用一次就可以输出数组的每一项。
由于内部迭代器迭代规则已经提前规定好了,如果我们不需要一次获取到数组所有的项,只需要一次获取一项或几项(例如我们经常遇到的分页问题)。那么内部迭代器显示不满足我们的需求。这里就需要用到外部迭代器。
### 外部迭代器
下面我们先通过一个简单的例子介绍如何使用JavaScript实现一个外部迭代器。
新建一个html文件,粘贴下面的代码保存html文件,用浏览器打开,F12打开开发者工具,点击下一个,会在Console中输入对应的值。
<!DOCTYPE html>
<html>
<body>
<script>
var each = function (ary, limit) {
var i = 0
return{
next: function () {
console.log(i)
if( i + limit <= ary.length) {
console.log(ary.slice(i, i + limit))
} else if(i <= ary.length -1) {
console.log(ary.slice(i, ary.length))
} else {
console.log('没有更多数据了')
}
i += limit
}
}
}
var e = new each([1,2,3,4,5,6,7,8,9,10], 3)
function next() {
e.next()
}
function reset() {
e = new each([1,2,3,4,5,6,7,8,9,10])
}
</script>
<p>
JavaScript 迭代器示例:
</p>
<input type="button" value="下一个" onclick="next()">
<input type="button" value="重置" onclick="reset()">
</body>
</html>
each函数就是一个迭代器,对外接收一个数组参数ary和步长limit(每次输出的数组项数),提供一个next的方法,当我们需要使用时new一个each对象 e , 每次我们只需调用e.next() 就可以得到数组下次内容。这里我们每次输出数组的3个项。log的内容如图:
其它几中迭代器
现实中还会遇到其它集中迭代器
- 倒序迭代器
- 终止迭代器
倒序迭代器
上面的内部迭代器是顺序循环数组的每一项,顾名思义,倒序迭代器就是从最后一项开始依次获取数组的每一项直到第一项。
var reverseEach = function (ary, callback) {
for (var l = ary.length - 1; l >= 0; l--) {
callback(l, ary[l]);
}
}
reverseEach([0, 1, 2], function (i, n) {
console.log(n); // 分别输出:2, 1 ,0
})
####终止迭代器
迭代器可以像for循环一样,提供一种跳出循环的方法。只需在迭代器内部约定一个条件,当满足该条件时就终止循环。
var each = function (ary, callback) {
for (var i = 0, l = ary.length; i < l; i++) {
if (callback(i, ary[i]) === false) { // callback 的执行结果返回false,提前终止迭代
break;
}
}
}
each([1, 2, 3, 4, 5], function (i, n) {
if (n > 3) { // n 大于3 的时候终止循环
return false;
}
console.log(n); // 分别输出:1, 2, 3
})
总结
迭代器是一种相对简单的模式,目前绝大多数语言都内置了迭代器。
使用场景
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 需要为聚合对象提供多种遍历方式。
- 为遍历不同的聚合结构提供一个统一的接口。
推荐资料:
使用leanCloud实现迭代查询(这是我个人在实际项目使用迭代模式的实例总结)