TIP
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。
# 实现自己的迭代器
var each = function (ary, callback) {
for (var i = 0, l = ary.length; i < 1; i++) {
callback(ary[i], i, ary[i])
}
}
each([1, 2, 3], function (i, n) {
alert([i, n])
})
# 内部迭代器
在函数内部已经定义好了迭代规则的迭代器称为内部迭代器,函数内部完全接手了整个迭代过程,外部只需要一次初始调用。
上面我们编写的each函数就属于内部迭代器。
# 外部迭代器
外部迭代器必须显示地请求迭代下一个元素。
外部迭代器增加了一些调用复杂度,但是也相对增强了迭代器的灵活性,可以手工控制迭代的过程或者顺序。
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
};
}
var compare = function (iterator1, iterator2) {
while(!iterator1.isDone() && !iterator2.isDone()){
if (iterator1.getCurrItem() !== iterator2.getCurrItem()){
throw new Error ('iterator1 和 iterator2 不相等')
}
iterator1.next()
iterator2.next()
}
alert ('iterator1 和 iterator2 相等')
}
var iterator1 = Iterator([ 1, 2, 3 ]);
var iterator2 = Iterator([ 1, 2, 3 ]);
compare( iterator1, iterator2 ); // 输出:iterator1 和 iterator2 相等
# 迭代数组和对象
迭代器模式不仅可以迭代数组,还可以迭代一些类数组的对象。
无论是内部迭代器还是外部迭代器,只要被迭代的聚合对象拥有length属性而且可以用下标访问,那它就可以被迭代。
# 倒序迭代器
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
});
# 中止迭代器
var each = function (ary, callback) {
for (var i = 0, l = ary.length; i < l; i++) {
if (callback(i, ary[i]) === false) {
break;
}
}
};
each([1, 2, 3, 4, 5], function(i, n) {
if (n > 3){
return false;
}
console.log(n); // 分别输出1, 2, 3
});
# 心得体会
JavaScript中已经内置了迭代器,比如forEach。es6中的Iterator就是一个标准的迭代器模式实现,使用生成器Generator可以快速生成一个迭代器。本章主要是学习迭代器模式的思想,实际用途不大。