javascript生成器是什么_yield关键字有什么作用?

16次阅读

生成器函数是用function声明的可暂停/恢复执行的特殊函数,返回Generator实例,本质为协程雏形;yield实现双向通信与惰性计算,yield委托迭代;适用于无限序列、手动异步控制及状态机建模。

javascript生成器是什么_yield关键字有什么作用?

生成器函数是能暂停/恢复执行的特殊函数

javaScript 生成器不是普通函数,它用 function* 声明,返回一个可迭代对象Generator 实例),本质是**协程雏形**——执行中途能停住、保存全部上下文(变量、作用域、执行位置),等你调用 next() 再继续。这不是语法糖,而是运行时机制级支持。

常见错误现象:直接调用 myGenerator() 不会执行函数体,只返回一个 Generator 对象;试图用 for...of 遍历但忘了它内部必须有 yield,结果循环不触发任何产出。

  • 必须用 next() 触发执行,首次调用才开始运行到第一个 yield
  • 每次 next() 返回 { value: ..., done: false/true },不是裸值
  • 生成器一旦 done: true,后续 next() 永远返回 { value: undefined, done: true }

yield 是暂停点,也是双向通信接口

yield 不是 return 的替代品,它是“暂停并交出控制权”的指令。关键在于:它既能向外产出值,也能向内接收值——下一次 next(value) 传入的参数,会成为当前 yield 表达式的返回值。

function* counter() {   let n = 0;   while (true) {     n = yield n; // ← 这里:产出 n,暂停;恢复时,传入的值赋给 n   } } 

const gen = counter(); gen.next(); // { value: 0, done: false } gen.next(10); // { value: 10, done: false } → n 变成 10 gen.next(100); // { value: 100, done: false }

  • 首次 next() 传参会被忽略(没地方接)
  • yield 后面的表达式只在暂停时求值,实现惰性计算
  • 若想让生成器提前结束,可用 gen.return(value) 或抛错 gen.throw(err)

yield* 是委托迭代,不是调用子函数

yield* 的核心作用是“把当前生成器的控制权透明转交给另一个可迭代对象”,包括其他 GeneratorArrayStringmap 等。它不是执行完子生成器再继续,而是像管道一样串联迭代流。

立即学习Java免费学习笔记(深入)”;

function* numbers() {   yield 1;   yield* [2, 3];      // ← 委托给数组,自动展开   yield 4; } 

[...numbers()]; // [1, 2, 3, 4]

  • yield* iter 中的 iter 必须是可迭代对象(有 [symbol.iterator]
  • 子迭代器的 throw()return() 会透传回父生成器,错误传播是连通的
  • 别写成 yield* someGenerator() 而不赋值——那只是创建并丢弃一个新生成器实例,没意义

实际用在哪?别硬套,先看这三类刚需场景

生成器不是炫技工具。真正值得用的地方很具体:

  • 无限序列或大数据:比如斐波那契、日志轮转、分页请求缓存——按需生成,不占内存
  • 手动控制异步流程:配合 co 库或手写 runner,把 promise 链变成同步写法(虽然后来被 async/await 覆盖,但理解它有助于读懂老项目)
  • 状态机建模:游戏 AI、表单步骤、协议解析——每个 yield 是一个稳定状态,next() 是外部触发的事件

容易被忽略的一点:生成器函数本身不能 await,但可以用 async function* 创建异步迭代器(ES2018+),这时 yield 产出的是 Promise,需搭配 for await...of 使用——这是两个不同层级的特性,混用前务必确认目标环境支持。

text=ZqhQzanResources