生成器函数用 function* 声明,调用返回 Generator 对象而非立即执行;yield 交出控制权并可接收 next() 传入的值,next() 返回 {value, done} 对象,for...of 遍历忽略 return 值。

生成器函数不是普通函数,它不会立即执行,而是返回一个可迭代的 Generator 对象;yield 不是暂停“当前函数”,而是交出控制权,等下一次 next() 调用时才从断点继续。
生成器函数声明和基本调用方式
必须用 function* 声明(星号紧贴 function 关键字),调用后不运行函数体,只返回 Generator 实例:
function* count() {
yield 1;
yield 2;
return 3;
}
const gen = count(); // 此刻什么都没打印
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: true }
-
next()是唯一触发执行的方式,每次调用都推进到下一个yield或函数结束 - 返回对象固定有两个属性:
value(yield后的值或return的值)和done(是否已结束) - 多次调用
next()超出 yield 数量时,value为undefined,done为true
yield 表达式能接收外部传入的值
yield 不只是“产出”,它本身是个表达式,可以被赋值——上一次 next(value) 传入的参数,会成为当前 yield 表达式的计算结果:
function* echo() {
const a = yield 'first';
console.log('a:', a); // 第二次 next(10) 传入的 10 在这里被接收
const b = yield 'second';
console.log('b:', b);
}
const it = echo();
console.log(it.next()); // { value: 'first', done: false }
console.log(it.next(10)); // a: 10 → { value: 'second', done: false }
console.log(it.next(20)); // b: 20 → { value: undefined, done: true }
- 第一次
next()传参无效(没地方接收),惯例传undefined或不传 - 后续每次
next(x)中的x,会成为**上一个**yield表达式的值 - 这个机制是实现双向通信、协程式流程控制的基础,比如配合
Promise手写async/await模拟
for...of 自动遍历生成器,但会忽略 return 值
for...of 隐式调用 next(),直到 done: true,但它只消费 yield 出的 value,不处理 return 的值:
立即学习“Java免费学习笔记(深入)”;
function* nums() {
yield 1;
yield 2;
return 'done!';
}
for (const n of nums()) {
console.log(n); // 只输出 1 和 2
}
// 'done!' 被丢弃了
- 如果需要捕获
return值,必须手动调用next()并检查done -
Array.from(nums())、[...nums()]等展开语法也只取yield值,同理忽略return - 生成器函数内部抛错(
throw)或外部用gen.throw()注入错误,会中断执行流——这点常被忽略,调试时容易卡在静默失败
真正难的不是写 yield,而是判断何时该用生成器:数据流需懒加载、状态机需精确控制暂停/恢复、或封装异步逻辑又不想用 async 时,才值得引入。否则,普通函数加数组更直白。











