【重读红宝书(JS高程4)】第7章-迭代器与生成器

72 阅读2分钟

这是重读红宝书(JavaScript高级程序设计 第4版)的第9篇文章,本节我们来看看代理:迭代器、生成器、它们的本质是什么、实际有哪些应用

本节涉及源码见仓库 github.com/adamswan/Re…

1、迭代器

Iterable,词根 Iter 来自拉丁语,翻译为“重复”

迭代器就是原型上有 Symbol.iterator 属性,属性值是一个函数,该函数就是迭代器工厂函数,返回值是一个指针对象,通过指针对象上的 .next() 方法就可以访问当前数据结构的每一项,因此就能拿来做遍历。

.next()方法返回的迭代器对象 IteratorResult 包含两个属性:done 和 value。

幸运的是,我们不需要手动调用迭代器工厂函数,for...of、扩展操作符等会自动调用函数,你可以将 for...of、扩展操作符 理解为:它们都是迭代器的语法糖。

很多内置类型都实现了 Iterable 接口:字符串、数组、Map、Set 等,但普通对象(字面量{})没有Iterable 接口。

为何有迭代器?以上数据结构的遍历方式各不相同,迭代器提供了一种统一的方式来遍历各种数据结构,使得代码更加通用和可复用。

// 自定义一个迭代器对象
function createIterator(items) {
  let index = 0;
  return {
    next: function () {
      const done = index >= items.length;
      const value = done ? undefined : items[index++];
      return {
        value,
        done,
      };
    },
  };
}

// 使用迭代器遍历数组
const arr = [1, 2, 3];
const iterator = createIterator(arr);

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 }

2、生成器

生成器是一种特殊的函数,它可以暂停和恢复执行。

生成器函数使用function*语法定义,在函数内部可以使用 yield 关键字暂停执行并返回一个值。

调用生成器并不会执行函数体,而是返回一个迭代器,使用迭代器的 next() 方法时,函数会从上次暂停的地方继续执行,直到遇到下一个 yield 或函数结束。

async、await 的底层其实是生成器

// 定义一个生成器函数
function* generatorFunction() {
  yield 1;
  yield 2;
  yield 3;
}

// 创建生成器对象
const generator = generatorFunction();

// 使用生成器对象进行迭代
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }

// 生成器可以直接用于 for...of 循环
for (const value of generatorFunction()) {
  console.log(value); // 依次输出 1, 2, 3
}