VVLL.net

迭代器和生成器

日期:2024-08-22 09:58:31

TypeScript 中的迭代器和生成器是用来处理序列的功能强大的工具。迭代器允许对象自定义其迭代行为,而生成器则提供了一种更便捷的方式来定义复杂的迭代逻辑。

1. 迭代器 (Iterators)

定义:迭代器是一个对象,它实现了 Iterator 接口,该接口包含一个 next 方法,返回一个包含 valuedone 属性的对象。

基本用法

// 定义一个迭代器
class SimpleIterator {
  private count: number = 0;
  private limit: number;

  constructor(limit: number) {
    this.limit = limit;
  }

  // 实现迭代器协议
  next() {
    if (this.count < this.limit) {
      return { value: this.count++, done: false };
    } else {
      return { value: undefined, done: true };
    }
  }
}

const iterator = new SimpleIterator(3);
console.log(iterator.next()); // { value: 0, done: false }
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

说明SimpleIterator 类实现了一个简单的迭代器,它生成从 0limit-1 的值。

2. 可迭代对象 (Iterable)

定义:一个对象被认为是可迭代的,如果它实现了 Iterable 接口,这意味着它有一个 Symbol.iterator 属性,返回一个迭代器。

基本用法

class NumberRange implements Iterable<number> {
  constructor(private start: number, private end: number) {}

  [Symbol.iterator]() {
    let current = this.start;
    const end = this.end;

    return {
      next() {
        if (current < end) {
          return { value: current++, done: false };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
}

const range = new NumberRange(1, 4);
for (const num of range) {
  console.log(num); // 1, 2, 3
}

说明NumberRange 类实现了 Iterable 接口,使得其实例可以使用 for...of 循环进行迭代。

3. 生成器 (Generators)

定义:生成器是一种特殊类型的函数,它可以暂停和恢复其执行。生成器函数使用 function* 语法定义,内部使用 yield 表达式来生成值。

基本用法

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

const generator = simpleGenerator();
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 }

说明simpleGenerator 函数每次 yield 一个值,当没有更多值时,返回 { value: undefined, done: true }

4. 使用生成器实现可迭代对象

定义和用法:生成器函数可以用于实现 Iterable 接口,使得自定义迭代逻辑更加简单。

class NumberRange {
  constructor(private start: number, private end: number) {}

  *[Symbol.iterator]() {
    for (let i = this.start; i < this.end; i++) {
      yield i;
    }
  }
}

const range = new NumberRange(1, 4);
for (const num of range) {
  console.log(num); // 1, 2, 3
}

说明NumberRange 类使用生成器函数实现了 Iterable 接口,使得迭代逻辑更简洁。

5. 生成器的高级用法

生成器除了简单地生成序列,还可以通过 yield 表达式和 next 方法之间的双向通信,实现更复杂的迭代逻辑。

双向通信

function* generatorWithInput() {
  const first = yield "first yield";
  console.log(`Received: ${first}`);
  const second = yield "second yield";
  console.log(`Received: ${second}`);
}

const generator = generatorWithInput();
console.log(generator.next()); // { value: "first yield", done: false }
console.log(generator.next("first input")); // { value: "second yield", done: false }
// Received: first input
console.log(generator.next("second input")); // { value: undefined, done: true }
// Received: second input

说明:生成器函数 generatorWithInput 演示了如何在调用 next 时向生成器发送值,并在生成器中接收这些值。

6. 异步生成器 (Async Generators)

定义:异步生成器函数使用 async function* 语法定义,允许在生成器函数中使用 await 表达式,从而处理异步操作。

基本用法

async function* asyncGenerator() {
  for (let i = 0; i < 3; i++) {
    await new Promise(resolve => setTimeout(resolve, 1000));
    yield i;
  }
}

(async () => {
  for await (const num of asyncGenerator()) {
    console.log(num); // 0, 1, 2 (每秒一个)
  }
})();

说明asyncGenerator 异步生成器函数每秒生成一个值,通过 for await...of 循环进行异步迭代。

总结

TypeScript 中的迭代器和生成器提供了强大的工具来处理序列和异步操作:

  • 迭代器:通过实现 Iterator 接口自定义迭代行为。
  • 可迭代对象:实现 Iterable 接口,使对象可以被 for...of 循环迭代。
  • 生成器:使用 function* 定义,使用 yield 表达式生成值,提供暂停和恢复执行的能力。
  • 异步生成器:使用 async function* 定义,允许在生成器中使用异步操作。

通过理解和应用这些特性,你可以编写更加灵活和高效的代码,处理复杂的迭代逻辑和异步操作。

参考

标签