JavaScript中的生成器函数详解

在 JavaScript 中,生成器函数 Generator Function 是一种特殊的函数,它允许你在函数执行过程中暂停和恢复。生成器函数通过 function* 语法定义,并使用 yield 关键字来控制函数的执行流程。生成器函数返回一个生成器对象,该对象遵循迭代器协议,可以逐步生成值。

以下是生成器函数的详细解析:

1. 基本语法

生成器函数使用 function* 定义,函数体内可以使用 yield 关键字来暂停函数的执行并返回一个值。

function* myGenerator() {yield 1;yield 2;yield 3;
}

function*:定义生成器函数的关键字。

yield:暂停函数执行并返回一个值。每次调用生成器对象的 next() 方法时,函数会从上次暂停的地方继续执行。

2. 生成器对象

生成器函数调用时不会立即执行函数体,而是返回一个生成器对象。这个生成器对象是一个迭代器,可以通过 next() 方法逐步执行生成器函数。

const gen = myGenerator();console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }

next():恢复生成器函数的执行,直到遇到下一个 yield 或函数结束。

返回一个对象,包含两个属性:

value:yield 表达式的值。

done:布尔值,表示生成器函数是否已经执行完毕。

3. yield 关键字

yield 是生成器函数的核心关键字,它的作用如下:

1. 暂停函数执行:当生成器函数执行到 yield 时,会暂停执行并返回 yield 后面的值;

2. 恢复函数执行:当调用生成器对象的 next() 方法时,函数会从上次暂停的地方继续执行,直到遇到下一个 yield 或函数结束;

function* myGenerator() {yield "Hello";yield "World";
}const gen = myGenerator();console.log(gen.next().value); // 'Hello'
console.log(gen.next().value); // 'World'
console.log(gen.next().done);  // true

4. yield* 表达式

yield* 用于委托给另一个生成器或可迭代对象(如数组、字符串等)。它允许在一个生成器函数中调用另一个生成器函数。

function* generator1() {yield 1;yield 2;
}function* generator2() {yield* generator1(); // 委托给 generator1yield 3;
}const gen = generator2();console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().done); // true

5. 生成器函数的特性

5.1. 惰性求值

生成器函数是惰性的,只有在调用 next() 时才会执行。这使得生成器非常适合处理大量数据或无限序列。

function* infiniteSequence() {let i = 0;while (true) {yield i++;}
}const gen = infiniteSequence();console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// 可以无限调用

5.2. 双向通信

生成器函数不仅可以通过 yield 返回值,还可以通过 next() 方法接收外部传入的值。

function* generator() {const x = yield "Hello";yield x;
}const gen = generator();console.log(gen.next().value); // 'Hello'
console.log(gen.next(42).value); // 42

第一次调用 next() 时,生成器函数执行到 yield 'Hello' 并暂停。

第二次调用 next(42) 时,42 会作为 yield 表达式的值传入,生成器函数继续执行。

5.3. 提前终止

生成器对象提供了 return() 和 throw() 方法,可以提前终止生成器函数的执行。

return(value):终止生成器函数并返回指定的值。

throw(error):在生成器函数内部抛出一个错误。

function* generator() {yield 1;yield 2;yield 3;
}const gen = generator();console.log(gen.next().value); // 1
console.log(gen.return(42).value); // 42
console.log(gen.next().done); // true

6. 生成器函数的应用场景

6.1. 惰性求值

生成器函数非常适合处理大量数据或无限序列,因为它只在需要时生成值。

function* fibonacci() {let [prev, curr] = [0, 1];while (true) {yield curr;[prev, curr] = [curr, prev + curr];}
}const fib = fibonacci();console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
console.log(fib.next().value); // 5

6.2. 异步编程

在 async/await 出现之前,生成器函数常用于简化异步编程。通过结合 Promise 和生成器,可以实现类似于 async/await 的效果。

function* asyncGenerator() {const result1 = yield new Promise((resolve) =>setTimeout(() => resolve(1), 1000));const result2 = yield new Promise((resolve) =>setTimeout(() => resolve(2), 1000));return result1 + result2;
}function runGenerator(generator) {const gen = generator();function handle(result) {if (result.done) return Promise.resolve(result.value);return Promise.resolve(result.value).then((res) => {return handle(gen.next(res));});}return handle(gen.next());
}runGenerator(asyncGenerator).then(console.log); // 3

6.3. 自定义迭代器

生成器函数可以用于创建自定义迭代器,简化迭代器的实现。

const myIterable = {*[Symbol.iterator]() {yield 1;yield 2;yield 3;},
};for (const value of myIterable) {console.log(value); // 1, 2, 3
}

7. 总结

1. 生成器函数使用 function* 定义,通过 yield 暂停和恢复执行;

2. 生成器函数返回一个生成器对象,该对象是一个迭代器,可以通过 next() 方法逐步执行;

3. yield* 用于委托给另一个生成器或可迭代对象;

4. 生成器函数适用于惰性求值、异步编程和自定义迭代器等场景;

生成器函数提供了一种强大的控制流机制,使得你可以更灵活地管理函数的执行过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/31224.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【问题记录】如何编译nv_peer_memory模块?依赖OFED的4个目录和2类文件?如何解决没有rdma/peer_mem.h文件?

背景 GDR:GPUDirect RDMA。这项新技术在 GPU 内存之间直接与 NVIDIA HCA/NIC 设备之间提供直接的 P2P(点对点)数据路径。这显着降低了 GPU-GPU 通信延迟,并完全减轻了 CPU 的负担。nv_peer_memory模块是网卡提供给GPU使用GDR技术…

3.6c语言

#define _CRT_SECURE_NO_WARNINGS #include <math.h> #include <stdio.h> int main() {int sum 0,i,j;for (j 1; j < 1000; j){sum 0;for (i 1; i < j; i){if (j % i 0){sum i;} }if (sum j){printf("%d是完数\n", j);}}return 0; }#de…

李彦宏:紧抓AI智能体爆发元年机遇 推动新质生产力加快发展

来源 人民网 3月5日公布的政府工作报告&#xff0c;“智能”一词被提及10次&#xff0c;“大模型”则首次被写入。作为大模型和人工智能领域的领军企业&#xff0c;我们感到非常振奋&#xff0c;同时深感责任重大。 报告在介绍今年政府工作任务时提出&#xff0c;“因地制宜发…

基于Python Django的人脸识别上课考勤系统(附源码,部署)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

5G基本概念

作者:私语茶馆 1. 5G应用场景概述 1.1.5G应用场景 ITU域2015年定义了三大应用场景:eMBB(增强型移动宽带)、uRLLC(低时延高可靠通信)、mMTC(海量物联网通信); emBB:Enhanced Mobile Broadband ,移动互联网应用,是4G MBB(移动宽带)的升级,主要侧重于网络速率、带…

VSCode+AI编程生态实战:从环境配置到智能编码的全栈指南

Python环境的搭建&#xff0c;我们选择了Anaconda环境&#xff0c;有Python环境&#xff0c;接下来要搭建当然是AI辅助编程环境了。在搭建这个之前&#xff0c;或者说大家在打算安装VSCode之前&#xff0c;需要先检查自已电脑是否已经安装了VSCode&#xff0c;因为这个软件是Wi…

Ubuntu工控卫士在制造企业中的应用案例

在当今数字化时代&#xff0c;信息安全已成为各行各业关注的焦点。特别是在工业控制领域&#xff0c;网络安全Linux工控机&#xff08;简称“工控卫士”&#xff09;作为信息安全防护的核心设备&#xff0c;正发挥着越来越重要的作用。本文将深入探讨工控卫士在信息安全防护场景…

Stable Diffusion教程|快速入门SD绘画原理与安装

什么是Stable Diffusion&#xff0c;什么是炼丹师&#xff1f;根据市场研究机构预测&#xff0c;到2025年全球AI绘画市场规模将达到100亿美元&#xff0c;其中Stable Diffusion&#xff08;简称SD&#xff09;作为一种先进的图像生成技术之一&#xff0c;市场份额也在不断增长&…

惊喜操作!强制DeepSeek和豆包轻松生成你的专属图片提示词

大家好&#xff0c;我是抖知书&#xff01;大伙儿平时用DeepSeek或者豆包&#xff0c;多半是写文章、搞数据&#xff0c;谁会天天想着用它生成图片啊&#xff1f;不过话说回来&#xff0c;还真有人动这个心思。 很多人大概觉得&#xff0c;AI不就是弄文字、数据的么&#xff1…

缓存之美:Guava Cache 相比于 Caffeine 差在哪里?

大家好&#xff0c;我是 方圆。本文将结合 Guava Cache 的源码来分析它的实现原理&#xff0c;并阐述它相比于 Caffeine Cache 在性能上的劣势。为了让大家对 Guava Cache 理解起来更容易&#xff0c;我们还是在开篇介绍它的原理&#xff1a; Guava Cache 通过分段&#xff08;…

日期类、Date、Calendar、IO 流、File

DAY9.2 Java核心基础 日期类 java对日期使用提供了良好的封装&#xff0c;包括java.util.Date和java.util.Calender Date Date类使用比较简单&#xff0c;直接通过构造函数实例化对象接口&#xff0c;Date对象标识当前的系统时间&#xff0c;默认的格式并不是我们所熟悉的&…

【Linux】详谈 基础I/O

目录 一、理解文件 狭义的理解&#xff1a; 广义理解&#xff1a; 文件操作的归类认知 系统角度 二、系统文件I/O 2.1 标志位的传递 系统级接口open ​编辑 open返回值 写入文件 读文件 三、文件描述符 3.1&#xff08;0 & 1 & 2&#xff09; 3.2 文件描…

【HarmonyOS Next之旅】DevEco Studio使用指南(二)

目录 1 -> 工程模板介绍 2 -> 创建一个新的工程 2.1 -> 创建和配置新工程 2.1.1 -> 创建HarmonyOS工程 2.2.2 -> 创建OpenHarmony工程 1 -> 工程模板介绍 DevEco Studio支持多种品类的应用/元服务开发&#xff0c;预置丰富的工程模板&#xff0c;可以根…

transformer模型介绍——大语言模型 LLMBook 学习(二)

1. transformer模型 1.1 注意力机制 **注意力机制&#xff08;Attention Mechanism&#xff09;**在人工智能中的应用&#xff0c;实际上是对人类认知系统中的注意力机制的一种模拟。它主要模仿了人类在处理信息时的选择性注意&#xff08;Selective Attention&#xff09;&a…

RAG 常见分块策略全解析:从原理到代码实践(2025 深度版)

大家好,我是大 F,深耕AI算法十余年,互联网大厂技术岗。 知行合一,不写水文,喜欢可关注,分享AI算法干货、技术心得。 更多文章可关注《大模型理论和实战》、《DeepSeek技术解析和实战》,一起探索技术的无限可能! 引言 在检索增强生成(RAG)系统中,分块策略是决定系统…

【论文解读】《START: Self-taught Reasoner with Tools》

链接&#xff1a;https://arxiv.org/pdf/2503.04625 1. 论文概述 解决现有大规模推理模型&#xff08;LRMs&#xff09;在复杂推理任务中容易产生幻觉&#xff08;hallucination&#xff09;以及内部推理效率低下的问题。提出一种工具集成的长链条思考&#xff08;Long Chain…

【问题处理】Vmware安装Centos Stream10无法加载安装界面

问题描述 使用Vmware17安装Centos Stream 10&#xff0c;安装界面无法成功加载&#xff0c;长时间显示为灰色&#xff0c;导致安装过程无法继续&#xff0c;如图所示。 问题原因 图形界面的渲染&#xff0c;相比于命令行界面&#xff0c;所需的硬件要求更高。 如果分配的C…

通义万相2.1开源版本地化部署攻略,生成视频再填利器

2025 年 2 月 25 日晚上 11&#xff1a;00 通义万相 2.1 开源发布&#xff0c;前两周太忙没空搞它&#xff0c;这个周末&#xff0c;也来本地化部署一个&#xff0c;体验生成效果如何&#xff0c;总的来说&#xff0c;它在国内文生视频、图生视频的行列处于领先位置&#xff0c…

线程--轻量化进程

1、什么是线程 在⼀个程序⾥的⼀个执⾏路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“⼀个进程内部的控制序列⼀切进程⾄少都有⼀个执⾏线程线程在进程内部运⾏&#xff0c;本质是在进程地址空间内运⾏在Linux系统中&#xff0c;在CPU眼中…

自动化测试脚本语言选择

测试人员在选择自动化测试脚本语言时面临多种选项。Python、Java、C#、JavaScript 和 Ruby 都是常见选择&#xff0c;但哪种语言最适合&#xff1f;本文将详细分析这些语言的特点、适用场景和优劣势&#xff0c;结合行业趋势和社会现象&#xff0c;为测试人员提供全面指导。 选…