0

0

javascript生成器函数如何工作?_学习javascript生成器与迭代器【教程】

夜晨

夜晨

发布时间:2026-01-28 14:17:02

|

715人浏览过

|

来源于php中文网

原创

JavaScript生成器函数是可暂停执行的函数,返回迭代器对象;调用后需用next()推进执行,yield暂停并输出值,return终止并设done: true。

javascript生成器函数如何工作?_学习javascript生成器与迭代器【教程】

JavaScript 生成器函数不是“异步函数的简化写法”,它本质是**可暂停执行的函数,返回一个迭代器对象**。你调用它不会立即运行函数体,而是得到一个 Generator 实例,只有调用它的 next() 方法时,才从头或上次暂停处继续执行,直到遇到下一个 yield 或函数结束。

生成器函数定义与基本调用:必须用 function* 语法

生成器函数声明必须带星号(function*),这是硬性语法要求;箭头函数不支持生成器。调用后返回的是一个迭代器对象,不是普通函数返回值:

function* count() {
  yield 1;
  yield 2;
  return 3;
}
const gen = count(); // 不执行函数体,只返回 Generator 对象
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: true }
  • yield 暂停并输出值,return 终止并设 done: true
  • 多次调用 next() 是推进执行的关键,不是“重跑函数”
  • 如果生成器已 done: true,后续 next() 仍返回 { value: undefined, done: true }

yield 可接收外部传入值:双向通信机制

yield 表达式本身是有返回值的——它等于下一次调用 next(arg) 时传入的参数。这是生成器实现协程式控制流的基础:

function* echo() {
  const a = yield 'first';
  console.log('a:', a); // a: 'hello'
  const b = yield 'second';
  console.log('b:', b); // b: 'world'
}
const it = echo();
console.log(it.next());      // { value: 'first', done: false }
console.log(it.next('hello')); // { value: 'second', done: false }
console.log(it.next('world')); // { value: undefined, done: true }
  • 首次 next() 总是忽略传参,只启动执行到第一个 yield
  • 后续 next(x) 中的 x 成为上一个 yield 表达式的值
  • 这个特性常被用于手写 co 类库、模拟 async/await 的早期实现

生成器与 for...of 和扩展运算符配合:自动消费迭代器

生成器对象实现了 Symbol.iterator,因此天然支持 for...of[...gen]Array.from(gen) 等语法,但注意:它们**只会遍历 yield 的值,忽略 return 的终值**:

Faceswap
Faceswap

免费开源的AI换脸工具

下载

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

function* nums() {
  yield 1;
  yield 2;
  return 999; // 这个 999 不会被 for...of 捕获
}
for (const n of nums()) {
  console.log(n); // 输出 1, 2 —— 不会输出 999
}
console.log([...nums()]); // [1, 2]
  • for...of 内部反复调用 next() 直到 done: true,但只收集 value 字段
  • 若需捕获 return 值,必须手动调用 next() 并检查 done
  • 生成器一旦 done,无法重置;如需重复使用,得重新调用生成器函数创建新实例

常见误用:把生成器当 Promise 用,或混淆 yieldawait

生成器本身不处理异步,yield 后跟 Promise 不会自动等待;要实现类似 async/await,必须配合同步驱动器(如 co 库或手写 runner):

function* fetchUser() {
  const res = yield fetch('/api/user'); // ❌ 这里 res 是 Promise 实例,不是响应结果
  return res.json();
}
// 必须用 runner 包装才能真正 await:
function run(genFn) {
  const it = genFn();
  function next(val) {
    const { value, done } = it.next(val);
    if (done) return value;
    return value.then(res => next(res)); // 手动 resolve Promise 并递归 next
  }
  return next();
}
  • 直接 yield Promise 没有意义,JS 引擎不会自动 await
  • 现代代码应优先用 async/await,生成器主要用于底层抽象(如 redux-saga)、状态机或需要精细控制执行节奏的场景
  • 调试时注意:生成器函数在 DevTools 中断点可能跳转不直观,因实际执行分散在多次 next() 调用中

生成器的核心价值不在“写起来多简洁”,而在于它把函数执行权交还给调用方——你可以决定何时推进、传什么数据、甚至中途注入异常(it.throw(err))。这种控制反转正是它难以被替代的地方,也是最容易被忽略的复杂性所在。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1501

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

232

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

514

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5306

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

481

2023.09.01

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.3万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号