设计模式-迭代器模式

222 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

什么是迭代器模式

迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即 使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

常见的迭代器如: Array.prototype.forEach():

迭代器是通过使用 next() 方法实现 Iterator protocol 的任何一个对象,该方法返回具有两个属性的对象:

  • value: 这是序列中的 next
  • done: 如果已经迭代到序列中的最后一个值,则它为 true

如果 valuedone 一起存在,则它是迭代器的返回值。

实现一个迭代器

const forEach = function (ary, callback) {
  for (let i = 0, l = ary.length; i < l; i++) {
    // 把索引和元素当作参数传给 callback 函数
    callback.call(ary[i], i, ary[i]);
  }
};
forEach([1, 2, 3], function (i, n) {
  console.log([i, n]);
});

内部迭代器

上面的 forEach 就是一个内部迭代器

优点:外界不需要关心迭代器内部的实现,只需要一次初始调用

缺点:内部迭代器的迭代规则在调用之前已经被制定好,无法修改

外部迭代器

外部迭代器必须显式地请求迭代下一个元素。

外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,我们可以手工控制 迭代的过程或者顺序。

我们创建一个简单的范围迭代器,接受三个参数(开始的索引,结束值,每次变化的范围)

function makeRangeIterator(start = 0, end = Infinity, step = 1) {
  let nextIndex = start;
  let iterationCount = 0;

  const rangeIterator = {
    next: function () {
      let result;
      if (nextIndex < end) {
        result = { value: nextIndex, done: false };
        nextIndex += step;
        iterationCount++;
        return result;
      }
      return { value: iterationCount, done: true };
    },
  };
  return rangeIterator;
}

使用上面的迭代器

let it = makeRangeIterator(1, 10, 2);

let result = it.next();
while (!result.done) {
  console.log(result.value); // 1 3 5 7 9
  result = it.next();
}

console.log('Iterated over sequence of size: ', result.value); // 5

总结

迭代器的模式较为简单,除了 forEach, 还有一些对象或者字面量的迭代。还有一些按顺序,倒序和一些终止迭代器(break)等。