当前位置: 首页 > news >正文

JavaScript 生成器函数核心用法与实践详解

生成器函数(Generator Function)是 JavaScript 中一个非常独特且强大的特性,你可以把它理解为一个可以“暂停”和“继续”的函数

为了让你更容易理解,我们可以做一个形象的对比:

  • 普通函数:像坐过山车。一旦启动,就必须一口气跑完全程,中间无法暂停,直到返回最终结果。
  • 生成器函数:像看Netflix/视频。你可以随时点击“暂停”,去喝杯水(执行其他代码),然后再点击“播放”,从刚才暂停的地方继续看,剧情(变量状态)完全保留。

1. 基础语法:两个新面孔

要掌握生成器,你只需要记住两个特殊的符号:

  1. function*:注意那个星号*,它告诉 JavaScript:“这是一个生成器函数,不是普通函数”。
  2. yield:这是生成器的灵魂。它的意思是“产出”或“暂停”。当代码执行到yield时,函数会暂停执行,并把yield后面的值交出去。

2. 代码实战:它是如何工作的?

让我们看一个最简单的例子,看看它是如何一步步执行的:

// 1. 定义生成器函数 function* myGenerator() { console.log("开始执行"); yield "第一次暂停"; // 遇到 yield,暂停,返回这个值 console.log("继续执行"); yield "第二次暂停"; // 再次遇到 yield,再次暂停 console.log("执行结束"); return "最终结果"; } // 2. 调用生成器函数 // 注意:这里调用并不会立即执行函数体! const gen = myGenerator(); // 3. 使用 .next() 方法控制执行 console.log(gen.next()); // 输出: "开始执行" // 返回: { value: "第一次暂停", done: false } console.log(gen.next()); // 输出: "继续执行" // 返回: { value: "第二次暂停", done: false } console.log(gen.next()); // 输出: "执行结束" // 返回: { value: "最终结果", done: true }

核心机制解析:

  • 返回对象:当你调用myGenerator()时,它返回了一个生成器对象(迭代器)。这个对象手里握着函数的“遥控器”。
  • next()方法:这是遥控器上的“播放/下一步”按钮。每次调用next(),函数就会执行到下一个yield处暂停。
  • 返回值结构:每次next()都会返回一个对象,包含两个属性:
    • valueyield后面跟着的值(或者是return的值)。
    • done:布尔值。false表示还没演完,true表示函数彻底执行完毕。

3. 进阶玩法:双向通信

这是生成器最神奇的地方。普通函数只能单向返回结果,但生成器可以**“有去有回”**。你可以通过next(数据)把数据传回给生成器内部。

规则next(参数)传入的参数,会变成上一个yield表达式的返回值。

function* talkGenerator() { // 1. 这里的变量 name 会接收外部传入的数据 // 注意:第一次 next() 的参数会被忽略,通常只用来启动 const name = yield "请问你叫什么名字?"; yield `你好,${name}!很高兴见到你。`; } const chat = talkGenerator(); // 第一步:启动生成器,获取第一个问题 console.log(chat.next().value); // 输出: "请问你叫什么名字?" // 第二步:把名字传回去 // "小明" 会赋值给上面的 name 变量 console.log(chat.next("小明").value); // 输出: "你好,小明!很高兴见到你。"

4. 为什么要用它?(实际场景)

你可能会问:“我为什么要写这么复杂的函数?” 生成器主要有三个核心用途:

惰性求值(省内存)

如果你需要生成一个包含 100 万个数字的数组,普通函数会一次性算出所有数字放入内存,导致内存爆炸。生成器可以**“用一个算一个”**。

function* infiniteNumbers() { let i = 0; while(true) { yield i++; // 只有你需要时,我才计算下一个数 } } const nums = infiniteNumbers(); nums.next().value; // 0 nums.next().value; // 1 // 永远不会内存溢出,因为它是按需生成的
遍历复杂数据结构

生成器非常适合用来遍历树形结构(比如文件目录、DOM 树)。

function* traverseTree(node) { if (!node) return; yield node.value; // 产出当前节点 // 递归委托 if (node.children) { for (const child of node.children) { yield* traverseTree(child); // yield* 可以委托另一个生成器 } } }
处理异步流程(历史背景)

async/await普及之前,生成器是解决“回调地狱”的主力军(配合co库)。虽然现在有了async/await(它本质上就是生成器的语法糖),但理解生成器有助于你理解异步编程的底层原理。

总结

  • 定义function*声明,yield暂停。
  • 执行:调用后不立即执行,返回一个迭代器对象。
  • 控制:用next()启动或恢复,用yield交出控制权。
  • 优势:可以分步执行、节省内存、处理无限数据流。

生成器函数是 JavaScript 中为数不多能让你手动控制函数执行节奏的工具,掌握它,你的代码逻辑控制能力会提升一个台阶!

http://www.jsqmd.com/news/584063/

相关文章:

  • OpenClaw技能开发入门:为Qwen3-14B定制专属自动化模块
  • 前端架构设计吐槽:别再让你的代码像坨翔!
  • 基于STM32的宠物寄养平台设计与实现
  • 大模型为什么需要 skill
  • 前端无障碍性吐槽:别再让残障人士用不了你的网站!
  • 从AI辅助到私有化部署:解析5款低代码工具
  • 低空安全刚需!西工大UAV-DETR反无人机小目标检测,参数减少40%,mAP50:95提升6.6个百分点
  • HPMSM的飞轮储能并网控制simulink仿真 MATLAB R2021b搭建
  • 激光切管卡盘:优特卡如何助力管材加工效率升级
  • 从零基础到PLC工程师:2026苏州3个月速成学习路径全解析
  • 基于域名分流的智能DNS
  • 2026年比较好的影像测量仪实力工厂推荐 - 品牌宣传支持者
  • 车辆动力学模型:Carsim与Simulink联合仿真解析空间位姿及速度随时间变化的动态特征
  • 基础ret2libc
  • 3.3 “给 Agent 一台电脑“——MCP 协议与开发者工具链深度集成
  • OpenClaw任务监控:gemma-3-12b-it执行日志的可视化分析
  • 高端制造企业如何设计薪酬体系吸引和留住高技能人才?
  • Serie嵌入式时间序列库:面向LPWAN的轻量级压缩框架
  • 2026二手名表回收鉴定实战:机芯、外观等多维度鉴定要点解析
  • 12306高铁票API预定接口开发文档
  • 【图书推荐】《Python大数据分析师的算法手册》
  • 重磅发布|中国移动智慧城市低空应用人工智能安全白皮书来袭
  • OpenClaw技能市场:Top10 Qwen3.5-9B实用插件推荐
  • 代码随想录算法训练营第十七天| LeetCode 654 最大二叉树、LeetCode 617 合并二叉树、LeetCode 700 二叉搜索树中的搜索、LeetCode 98 验证二叉搜索树
  • idea低版本用高版本的jdk
  • 3.2 虚拟文件系统设计:工作空间隔离与产物版本管理的工程实践
  • COMSOL天然气水合物温压力化四场耦合模拟那些事儿
  • OpenClaw成本优化方案:千问3.5-27B自建接口替代OpenAI
  • 在银滩附近玩,周边有什么好吃的推荐?
  • 软考中级九大科目资料合集!当初翻遍全网整理的,现在一次性无偿分享