babel 转译 generator 函数本质是将其转为基于状态机的 es5 兼容函数,通过 regeneratorruntime.mark 包裹、switch-case 拆解 yield、引入 regenerator-runtime 运行时实现兼容;是否转译取决于 targets 配置。

Babel 转译 Generator 函数,本质是把它变成能在 ES5 环境中运行的、基于状态机的函数,而不是直接执行或模拟异步行为。它不改变语义,只改写结构——让你写的 function* 和 yield 在老浏览器里也能“跑起来”。
Generator 被转成什么样子?
比如你写:
function* count() {
yield 1;
yield 2;
return 3;
}
Babel(配合 @babel/preset-env)会把它编译成一个返回 regeneratorRuntime.mark 包裹的函数,并用内部状态变量控制执行流程。核心变化包括:
- 原函数被包裹进
regeneratorRuntime.mark(),标记为 generator 函数 -
yield表达式被拆解为条件判断 + 状态跳转(如context.next、context.done) - 整个逻辑被重构为一个大 switch-case 状态机,每个
yield对应一个case分支 - 返回值不再直接是
Iterator,而是由regeneratorRuntime.wrap()封装的可迭代对象
必须引入 regenerator-runtime
因为 Babel 只负责语法转换,不提供运行时支持。Generator 的底层调度依赖 regeneratorRuntime,所以你需要手动加载:
- 开发时:在入口文件顶部加
import "regenerator-runtime/runtime"; - 或通过
core-js启用:useBuiltIns: 'usage'会自动注入(前提是配置了corejs: { version: 3, proposals: true }) - 注意:
@babel/plugin-transform-runtime会自动引入regenerator-runtime,但需确保已安装@babel/runtime并启用该插件
目标环境决定是否需要转译
不是所有场景都要转。Babel 根据 targets 判断:
- 若
browsers: ['Chrome >= 63', 'Edge >= 79'],这些浏览器原生支持 Generator,Babel 默认跳过转译 - 若包含 IE11 或旧版 Safari,
@babel/preset-env会自动启用@babel/plugin-transform-regenerator - 可通过
.babelrc显式开启:{"plugins": ["@babel/plugin-transform-regenerator"]}
实际效果:yield 不再是语法糖,而是状态切换
转译后,每次调用 next() 实际是在驱动一个闭包内的状态变量(如 context.prev、context.tryEntries),而不是靠引擎原生协程。这意味着:
- 可以调试、断点、逐步执行(虽然代码变长了)
- 与 Promise 混用时(如
async/await),Babel 通常优先转async,而Generator仅在显式使用时才处理 - 如果项目已全面用
async/await,Generator 的转译基本只出现在遗留代码或特定库中
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











