生成器函数用function*声明,调用返回迭代器,需next()触发执行;yield暂停并交出控制权,可接收next传入值;return终止生成器;不可重用,非为替代循环而生。

JavaScript 生成器不是普通函数,它能暂停执行、交出控制权,并在后续恢复——yield 就是这个暂停和交出的指令。
生成器函数怎么声明和调用?
生成器函数必须用 function* 声明(星号紧贴 function 关键字),调用后不立即执行,而是返回一个迭代器对象。
- 错误写法:
function myGen() { yield 1; }→ 语法报错,缺少* - 正确写法:
function* myGen() { yield 1; yield 2; } - 调用后得到的是迭代器:
const it = myGen();,此时函数体未运行 - 真正触发执行要靠
it.next(),第一次调用才开始运行到第一个yield
yield 返回什么?怎么接收传入值?
yield 表达式本身有返回值:它会把外部通过 next(value) 传入的 value 作为本次 yield 表达式的计算结果。
-
it.next()(无参)时,yield表达式值为undefined -
it.next(42)时,当前yield左边的变量会接收到42,例如:const x = yield 1;→x变成42 - 每次
next()返回形如{ value: ..., done: ... }的对象,value是yield后面的值(或return的值),done表示是否结束
生成器里能用 return 吗?和 yield 有什么区别?
可以,但语义不同:return 表示生成器彻底结束,后续 next() 调用都返回 { value: undefined, done: true };而 yield 是暂停,还能继续。
立即学习“Java免费学习笔记(深入)”;
-
yield 1;→ 返回{ value: 1, done: false } -
return 2;→ 返回{ value: 2, done: true } - 如果生成器函数体结束没写
return,最后一步自动返回{ value: undefined, done: true } -
throw()和return()方法也能强制结束生成器,但会跳过后续yield
常见误用和性能注意点
生成器不是为替代循环而生的,它的核心价值在于“可中断的同步逻辑”或手动控制异步流程(比如早期 co 库)。滥用会导致可读性下降和意外状态。
- 不要在箭头函数里用
function*—— 箭头函数不能是生成器 -
yield只能在生成器函数内使用,嵌套普通函数里直接报Uncaught SyntaxError: Unexpected identifier - 生成器对象不可重用:一旦
done: true,再次next()永远返回{ value: undefined, done: true } - V8 对生成器有优化,但大量短生命周期生成器(比如每次渲染都新建)可能比数组 map 慢,别为了“酷”硬套
最易被忽略的一点:生成器的“暂停点”只存在于 yield 表达式求值完成之后,不是语句开头;也就是说,yield foo() 会先执行 foo(),再暂停并返回其结果——这决定了副作用发生的时机。











