简述ES6 Generator函数的作用?

参考回答

ES6 的 Generator 函数 是一种特殊的函数,可以用来生成 迭代器(Iterator)。它通过 function* 定义,运行时不会立即执行,而是可以通过调用其生成的迭代器对象的 next 方法,按需执行代码的某部分。Generator 的作用包括:

  1. 控制函数执行过程:可以暂停和恢复函数的执行。
  2. 实现异步编程:通过暂停点依次执行异步任务,避免回调嵌套。
  3. 生成序列:方便地生成自定义数据序列。

示例:

function* generatorExample() {
  yield 'Hello';
  yield 'World';
  return 'Done';
}

const gen = generatorExample();
console.log(gen.next()); // { value: 'Hello', done: false }
console.log(gen.next()); // { value: 'World', done: false }
console.log(gen.next()); // { value: 'Done', done: true }

详细讲解与拓展

1. Generator 函数的语法

Generator 函数的定义形式是在 function 后添加 *,并使用 yield 关键字来定义暂停点:

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

特点
– 调用 Generator 函数不会立即执行,而是返回一个 迭代器对象
– 每次调用 next() 方法时,函数会执行到下一个 yield,并暂停,直到下一次调用 next()
yield 会返回后面表达式的值,而 next() 可以接受一个参数作为上一个 yield 表达式的返回值。


2. Generator 的作用和应用场景

(1)控制函数执行

Generator 允许函数在运行中暂停和恢复,提供了对函数执行过程的精细控制:

function* controlFlow() {
  console.log('Step 1');
  yield;
  console.log('Step 2');
  yield;
  console.log('Step 3');
}

const flow = controlFlow();
flow.next(); // 输出: Step 1
flow.next(); // 输出: Step 2
flow.next(); // 输出: Step 3
(2)生成数据序列

通过 yield,可以按需生成一系列值,避免一次性生成大量数据占用内存。

function* generateSequence(start, end) {
  for (let i = start; i <= end; i++) {
    yield i;
  }
}

const sequence = generateSequence(1, 5);
for (const value of sequence) {
  console.log(value); // 输出: 1, 2, 3, 4, 5
}
(3)实现无限序列

可以轻松生成无限序列,比如斐波那契数列:

function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

const fib = fibonacci();
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
(4)异步编程(控制异步任务)

Generator 可以通过暂停点和 yield 将异步操作的执行过程串联起来,简化异步代码的编写(类似于 async/await 的实现)。

function* fetchData() {
  const data1 = yield fetch('https://api.example.com/data1').then(res => res.json());
  console.log(data1);
  const data2 = yield fetch('https://api.example.com/data2').then(res => res.json());
  console.log(data2);
}

// 手动运行 Generator
const gen = fetchData();
gen.next().value.then(data1 => gen.next(data1).value.then(data2 => gen.next(data2)));
(5)实现协程(Coroutines)

Generator 可以实现多任务协作,在不同任务之间切换:

function* task1() {
  console.log('Task 1: Start');
  yield;
  console.log('Task 1: End');
}

function* task2() {
  console.log('Task 2: Start');
  yield;
  console.log('Task 2: End');
}

const t1 = task1();
const t2 = task2();

t1.next();
t2.next();
t1.next();
t2.next();
// 输出顺序: Task 1: Start -> Task 2: Start -> Task 1: End -> Task 2: End

3. Generator 的方法

方法 描述
gen.next(value) 向 Generator 恢复执行,并可传递一个值作为上一个 yield 的返回值。
gen.return(value) 终止 Generator 的执行,并可传递一个值作为返回值。
gen.throw(error) 向 Generator 中抛出一个错误。
示例:
function* example() {
  try {
    const result = yield 'Hello';
    console.log(result);
  } catch (e) {
    console.log('Error caught:', e);
  }
}

const gen = example();
console.log(gen.next()); // { value: 'Hello', done: false }
gen.throw(new Error('Something went wrong')); // 输出: Error caught: Something went wrong

4. Generator 与 Iterator 的关系

Generator 是实现迭代器(Iterator)的便捷方式:
– 调用 Generator 函数会返回一个迭代器对象。
– 迭代器对象实现了 Symbol.iterator 方法,因此可以直接用于 for...of

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

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

总结

Generator 函数是 ES6 提供的一种强大的工具,用于按需生成值、控制函数执行过程以及简化异步编程逻辑。它可以暂停和恢复函数的执行,结合迭代器协议,生成自定义序列,同时支持异步任务的同步写法。尽管使用稍显复杂,但 Generator 为更复杂的功能(如协程和异步控制流)提供了基础。

发表评论

后才能评论