javascript 高级编程系列 - 生成器函数迭代器参数区别

生成器函数(Generator Function)执行后返回一个迭代器。当我们调用这个迭代器的 next() 方法时,是否传入参数有着本质的区别


核心结论

  • 不传参数yield 表达式返回 undefined,生成器从上次暂停的位置继续执行。
  • 传参数:传入的参数会成为上一个 yield 表达式(即暂停点)的返回值,生成器从这个位置继续执行。

简单记法next(value) 是“喂”给生成器的值,它作为上一个 yield 的返回值


1. 不传参数的情况

function* gen() {
  const a = yield 1;
  console.log('a =', a);
  const b = yield 2;
  console.log('b =', b);
  return 3;
}

const it = gen();

console.log(it.next());      // { value: 1, done: false }
console.log(it.next());      // a = undefined
                            // { value: 2, done: false }
console.log(it.next());      // b = undefined
                            // { value: 3, done: true }
  • 第一个 next():执行到 yield 1,暂停,返回 1
  • 第二个 next():从上个暂停点恢复,yield 1 这个表达式的结果是 undefined,赋值给 a。然后继续到 yield 2,返回 2
  • 第三个 next()yield 2 的结果是 undefined,赋值给 b。最后 return 3

2. 传参数的情况

function* gen() {
  const a = yield 1;
  console.log('a =', a);
  const b = yield 2;
  console.log('b =', b);
  return 3;
}

const it = gen();

console.log(it.next());          // { value: 1, done: false }
console.log(it.next('hello'));   // a = hello
                                // { value: 2, done: false }
console.log(it.next('world'));   // b = world
                                // { value: 3, done: true }
  • 第一个 next():无法传参(因为还没有遇到 yield),参数被忽略。
  • 第二个 next('hello')'hello' 成为上一个 yield(yield 1)的返回值,赋值给 a
  • 第三个 next('world')'world' 成为上一个 yield(yield 2)的返回值,赋值给 b

3. 第一个 next() 的特殊性

第一个 next() 不能传参生效,因为此时生成器还没有执行到任何 yield 表达式。

function* gen() {
  const x = yield 10;
  console.log(x);
}

const it = gen();
it.next('test');  // 参数 'test' 被忽略
it.next();        // x = undefined

如果想要在生成器启动时传递初始值,应该通过生成器函数的参数:

function* gen(initial) {
  console.log('initial =', initial);
  yield initial + 1;
}

const it = gen(100);
it.next(); // initial = 100, { value: 101, done: false }

4. 为什么需要这种设计?

这种机制让生成器可以和外部进行双向通信

function* ask() {
  const name = yield '你叫什么名字?';
  const age = yield `你好 ${name},你多大了?`;
  return `${name} 今年 ${age} 岁。`;
}

const it = ask();
console.log(it.next().value);        // 你叫什么名字?
console.log(it.next('小明').value);  // 你好 小明,你多大了?
console.log(it.next(18).value);      // 小明 今年 18 岁。
  • 生成器向外部“询问”信息
  • 外部通过 next() 参数“回答”问题

5. 一个容易混淆的点

next(value) 的参数不是当前 yield 的返回值,而是上一个 yield 的返回值。

function* demo() {
  console.log('开始');
  const x = yield 1;    // ← 这个 yield 的值由下一次 next() 提供
  console.log('x =', x);
  yield 2;
}

const it = demo();
it.next();          // 输出: 开始
                    // 返回: { value: 1, done: false }
it.next(100);       // 输出: x = 100
                    // 返回: { value: 2, done: false }

时间线:

  1. 第一次 next():执行到 yield 1,暂停,返回 1
  2. 第二次 next(100):从暂停点恢复,yield 1 这个表达式得到值 100 → 赋值给 x

总结对比表

调用方式 作用 第一个 next() 是否有效
next() 恢复执行,上一个 yield 返回 undefined ✅ 可调用,参数无效
next(value) 恢复执行,上一个 yield 返回 value ❌ 参数被忽略

核心记忆点:

  • yield 就像向外部请求一个值
  • next(value) 就是外部给这个请求的回应
posted @ 2026-03-11 09:38  箫笛  阅读(1)  评论(0)    收藏  举报