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可以快速生成一个迭代器。本章主要是学习迭代器模式的思想,实际用途不大。