什么是迭代器和生成器?

迭代器和生成器是ES6引入的用于自定义和控制迭代流程的强大工具。它们构成了JavaScript中for...of循环和异步编程的基础,让你能够按需、懒加载地处理数据序列。

迭代器协议

迭代器是一个带有特定接口的对象。它必须有一个next()方法,该方法返回一个包含valuedone两个属性的对象。value是当前迭代的值,done是一个布尔值,表示迭代是否已完成。

function createCounterIterator(max) {
  let count = 1;
  return {
    next() {
      if (count <= max) {
        return { value: count++, done: false };
      }
      return { value: undefined, done: true };
    }
  };
}
const iterator = createCounterIterator(3);
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

任何实现了这种next()方法的对象都被称为迭代器。你可以手动调用next()来逐个获取值,直到donetrue

可迭代协议

一个对象要成为可迭代的(即可被for...of循环),它必须实现@@iterator方法,即拥有一个键为Symbol.iterator的属性。该方法返回一个迭代器对象。

const myIterable = {
  [Symbol.iterator]() {
    return createCounterIterator(3);
  }
};
for (let value of myIterable) {
  console.log(value); // 依次输出 1, 2, 3
}

数组、字符串、Map、Set等内置类型之所以可以被for...of遍历,正是因为它们内建了Symbol.iterator方法。

生成器函数

手动实现迭代器协议略显繁琐。生成器函数则提供了一种更简洁的语法来创建迭代器。在function关键字后加一个星号*就定义了一个生成器函数。

function* counterGenerator(max) {
  for (let i = 1; i <= max; i++) {
    yield i;
  }
}
const gen = counterGenerator(3);
console.log(gen.next()); // { value: 1, done: false }
for (let num of counterGenerator(3)) {
  console.log(num); // 依次输出 1, 2, 3
}

生成器函数在调用时不会立即执行,而是返回一个生成器对象(它同时遵守迭代器协议)。当调用其next()方法时,函数会执行到下一个yield表达式,并将yield后面的值作为value返回,然后函数暂停。下次调用next()时,再从暂停处继续执行。

生成器的强大之处

生成器不仅简化了迭代器的创建,还支持双向通信。你可以通过next()方法向生成器内部传递值,这个值会成为上次yield表达式的返回值。

function* twoWayGenerator() {
  const received = yield 'Hello';
  yield `You said: ${received}`;
}
const tw = twoWayGenerator();
console.log(tw.next()); // { value: 'Hello', done: false }
console.log(tw.next('World')); // { value: 'You said: World', done: false }

此外,生成器与yield*表达式结合,可以轻松地委托给另一个可迭代对象或生成器,实现递归或组合迭代。

迭代器和生成器是处理无限序列(如斐波那契数列)、懒加载数据、状态机以及实现自定义数据结构的理想选择。它们也是现代异步编程模式async/await的底层基础,其中async函数本质上就是一种特殊的生成器。

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容