JavaScript 迭代器和生成器

242 阅读2分钟

JavaScript 迭代器和生成器

作为一种面向对象的脚本语言,JavaScript 支持几乎所有的编程模式。在迭代和遍历数据集时,迭代器和生成器是两个非常重要的概念,它们可以大幅提高代码的复用性和可读性。

迭代器

迭代器是指一种用于遍历数据集合的特定对象。迭代器提供了一个统一的访问数据集合的接口,可以为各种数据集合提供一致的遍历方式,包括数组、Map、Set 等。

在 JavaScript 中,迭代器是通过内置的 Symbol.iterator 构造出来的,可以使用 for...of 循环语句来实现迭代。

const myArray = [1, 2, 3, 4, 5];
const iterator = myArray[Symbol.iterator]();
for (const num of iterator) {
  console.log(num);
}

上面的代码中,使用 for...of 循环遍历了一个数组,并使用内置的 Symbol.iterator 构造出迭代器。接着使用 for...of 循环语句进行迭代,并打印出每一个数组元素。

还可以自定义迭代器,实现对数据的灵活遍历。以下是一个对实际应用场景封装的简单示例:

function makeIterator(array) {
  let nextIndex = 0;
  return {
    next: () => {
      return nextIndex < array.length
      ?
      {value: array[nextIndex++], done: false}
      :
      {done: true};
    }
  }
}

const iter = makeIterator(['hello', 'world']);
console.log(iter.next().value); // 'hello'
console.log(iter.next().value); // 'world'

上述代码中,通过自定义 makeIterator 函数,使其返回一个包含 next() 方法的对象。每次执行 next() 方法时,判断 nextIndex 是否小于数组长度,如果是,则返回数组中该位置对应的值和 done 值为 false,表示还有下一个元素;否则,返回 done 值为 true,表示到达了数据结尾。

生成器

ES6 引入了 generator,它也是一种迭代器,但是数据可以逐个产生,可以更加灵活。generator 使用 function* 构造函数来生成,函数内部可以使用 yield 关键字产生数据、暂停函数执行、用于下次执行等。

以下是一个简单的实例:

function* generator() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = generator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3

generator 内部使用 yield 关键字产生了三个数据,并暂停了函数的执行。接着,依次执行 next() 方法时,可以依次取到每一个产生的数据。

generator 也可以和其他迭代器和生成器一起使用,可以用于复杂的数据流和异步操作等场景。以下是一个结合 Promise 的示例:

function* generateData() {
  const data1 = yield new Promise(resolve => setTimeout(() => resolve(1), 1000));
  const data2 = yield new Promise(resolve => setTimeout(() => resolve(2), 1000));
  const data3 = yield new Promise(resolve => setTimeout(() => resolve(3), 1000));
  return data1 + data2 + data3;
}

(async function() {
  const gen = generateData();
  const result1 = await gen.next().value;
  const result2 = await gen.next().value;
  const result3 = await gen.next().value;
  const result = await gen.next().value;
  console.log(result1, result2, result3, result); // 1, 2, 3, 6
})();

在上面的示例中,使用 generator 和 Promise 一起实现了异步操作,每个 Promise 的结果都被 yield 关键字产生,然后使用 async/await 异步操作和 next() 方法实现了每个 Promise 的依次执行。最后,将每个 Promise 的结果累加并打印输出。

总结

迭代器和生成器是 JavaScript 中重要的数据遍历和产生工具。它们可以大幅提高代码的复用性和可读性,同时也很好地支持了 JavaScript 在异步操作方面的发展。在实际开发中,需要熟练掌握迭代器和生成器的使用及相关技巧,创造出易于维护和扩展的高质量代码。