Skip to content

迭代器与生成器

ES6(ECMAScript 2015)引入了迭代器(Iterators)和生成器(Generators),为 JavaScript 提供了更强大的控制流功能,特别是在处理循环和异步编程方面。它们使得代码更加简洁、直观,并提高了可读性和维护性。

迭代器

迭代器是一种对象,它定义了一个序列的值(或键值对)的获取方式,并跟踪当前遍历的指针位置。在 ES6 中,任何实现了Iterator协议的对象都可以被称为迭代器。该协议要求实现一个名为next()的方法,此方法返回一个包含valuedone两个属性的对象。

  • 创建一个简单的迭代器:
javascript
function makeIterator(array) {
  let index = 0;

  return {
    next: function () {
      if (index < array.length) {
        return { value: array[index++], done: false };
      } else {
        return { value: undefined, done: true };
      }
    },
  };
}

let it = makeIterator(["a", "b", "c"]);
console.log(it.next()); // 输出: { value: "a", done: false }
console.log(it.next()); // 输出: { value: "b", done: false }
console.log(it.next()); // 输出: { value: "c", done: false }
console.log(it.next()); // 输出: { value: undefined, done: true }

可迭代对象

为了使对象成为可迭代对象,需要实现[Symbol.iterator]方法,该方法返回一个迭代器。

  • 创建一个自定义的可迭代对象:
javascript
let myIterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  },
};

for (let value of myIterable) {
  console.log(value); // 输出: 1, 2, 3
}

生成器

生成器函数是使用function*语法声明的特殊函数,它可以暂停执行并稍后恢复,每次执行到yield语句时都会暂停。生成器非常适合用于复杂的控制流逻辑,比如异步流程控制。

  • 基本生成器函数示例:
javascript
function* generatorFunction() {
  yield 1;
  yield 2;
  yield 3;
}

let gen = generatorFunction();
console.log(gen.next()); // 输出: { value: 1, done: false }
console.log(gen.next()); // 输出: { value: 2, done: false }
console.log(gen.next()); // 输出: { value: 3, done: false }
console.log(gen.next()); // 输出: { value: undefined, done: true }

使用生成器进行异步操作

生成器可以与 Promises 结合使用来简化异步代码的编写。虽然这在现代 JavaScript 中更多地被async/await所替代,但在某些情况下,生成器仍然非常有用。

  • 结合 Promise 使用生成器模拟async/await
javascript
function asyncFunction() {
  return new Promise((resolve) => {
    setTimeout(() => resolve("完成"), 1000);
  });
}

function* main() {
  const result = yield asyncFunction(); // 暂停直到Promise解决
  console.log(result); // 输出: 完成
}

function execute(generator) {
  const iterator = generator();

  function handle(iteratorResult) {
    if (!iteratorResult.done) {
      iteratorResult.value.then(
        (res) => handle(iterator.next(res)),
        (err) => iterator.throw(err)
      );
    }
  }

  handle(iterator.next());
}

execute(main);

通过这些新特性,ES6 大大增强了 JavaScript 处理复杂数据结构和控制流的能力,特别是对于异步编程的支持,使得代码更加简洁和易于理解。

Released under the MIT License.