news 2026/7/28 19:19:38

Generator函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Generator函数

一、Generator的基本概念

1.定义Gernerator函数

Generator是一种函数,这种函数是ES6提出的一种异步编程的解决方案,在它内部,使用yield关键字封装了一个个状态机。这个函数的执行结果,就是一个遍历器对象。

function*next(){yield1;yield2+2;return3;}varfun=next();console.log(fun.next());//{value: 1, done: false}console.log(fun.next());//{value: 4, done: false}console.log(fun.next());//{value: 3, done: true}console.log(fun.next());//{value: undefined, done: true}

Generator函数,返回的是一个遍历器对象,这个遍历器对象,拥有next方法,调用这个方法,就能得到yield关键字标识状态的结果。

2.Generator函数特征
  • function 关键字和函数之间有一个星号(*),且内部使用yield表达式,定义不同的内部状态
  • 调用Generator函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象
  • Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行
3.异步编程

所谓异步,简单说就是一个任务分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

异步编程方式:

  • 回调函数
  • 事件监听
  • 发布/订阅者
  • Promise对象

所谓回调函数,就是把第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。回调函数的异步方式容易形成多重嵌套,多个异步操作形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改。这种情况就称为”回调函数地狱”(callback hell)。Promise可以解决callback hell问题,Promise对象允许回调函数的嵌套,改成链式调用。

Generator函数之所以是一种完美的异步编程解决方案,本质上是因为它的两个特点:函数体内外的数据交换完美的错误处理机制

二、yield 表达式

Generator 函数返回的遍历器对象,只有调用 next 方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。

1.yield 表达式就是暂停标志

yield 表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行

2.使用yield需注意
  • yield语句只能用于function*的作用域,如果function*的内部还定义了其他的普通函数,则函数内部不允许使用yield语句
  • yield语句如果参与运算,必须用括号括起来

三、next() 方法

1.next 方法参数

表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。V8 引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。从语义上讲,第一个next方法用来启动遍历器对象,所以不用带有参数。

2.遍历器对象的 next 方法的运行逻辑
  • 遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
  • 下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
  • 如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
  • 如果该函数没有return语句,则返回的对象的value属性值为undefined
3.return 方法跟 next 方法的区别
  • return终结遍历,之后的yield语句都失效;next返回本次yield语句的返回值。
  • return没有参数的时候,返回{ value: undefined, done: true }next没有参数的时候返回本次yield语句的返回值。
  • return有参数的时候,覆盖本次yield语句的返回值,也就是说,返回{ value: 参数, done: true }next有参数的时候,覆盖上次yield语句的返回值,返回值可能跟参数有关(参数参与计算的话),也可能跟参数无关(参数不参与计算)。
4.for…of 循环

可以自动遍历Generator函数时生成的Iterator对象,且此时不再需要调用next方法。一旦next方法的返回对象的done属性为truefor…of循环就会中止,且不包含该返回对象。

5.示例

next()方法

// 定义一个Generator函数function*foo(x){vary=2*(yield(x+1));varz=yield(y/3);return(x+y+z);}vara=foo(5);console.log(a.next());// Object{value:6, done:false} 第一次调用a的next方法时,返回x+1的值6console.log(a.next());// Object{value:NaN, done:false} 第二次运行next方法的时候不带参数,导致y的值等于2 * undefined(即NaN),除以3以后还是NaNconsole.log(a.next());// Object{value:NaN, done:true} 第三次运行Next方法的时候不带参数,所以z等于undefined,返回对象的value属性等于5 + NaN + undefined,即NaN。varb=foo(5);console.log(b.next());// {value:6, done:false } 第一次调用b的next方法时,返回x+1的值6console.log(b.next(12));// {value:8, done:false } 第二次调用next方法,将上一次yield表达式的值设为12,因此y等于24,返回y / 3的值8;console.log(b.next(13));// {value:42, done:true } 第三次调用next方法,将上一次yield表达式的值设为13,因此z等于13,这时x等于5,y等于24,所以return语句的值等于42。

Genarator 部署Ajax操作

function*main(){// 通过 Ajax 操作获取数据varresult=yieldrequest("http://some.url");varres=JSON.parse(result);console.log(res.value);}functionrequest(url){makeAjaxCall(url,function(res){it.next(res);})}varit=main();console.log(it.next());

Genarator 对任意对象部署 Iterator 接口

function*deployObjectInterface(obj){letkeys=Object.keys(obj);for(leti=0;i<keys.length;i++){letkey=keys[i];yield[key,obj[key]];}}letobj={name:"Cynthia",age:21};for(let[key,value]ofdeployObjectInterface(obj)){console.log(key,value);}// name Cynthia// age 21

Genarator 对数组部署 Iterator 接口

function*deployArrayInterface(arr){varnextIndex=0;while(nextIndex<arr.length){yieldarr[nextIndex++];}}vararr=deployArrayInterface(['name','age']);console.log(arr.next());// {value: "name", done: false}console.log(arr.next().value);// nameconsole.log(arr.next().done);// falseconsole.log(arr.next().value);// ageconsole.log(arr.next().done);// trueconsole.log(arr.next().value);// undefinedconsole.log(arr.next().done);// true
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/28 19:18:46

Spring全家桶源码核心宝典:Java进阶必备!

Spring是我们Java程序员面试和工作都绕不开的重难点。很多粉丝就经常跟我反馈说由Spring衍生出来的一系列框架太多了&#xff0c;根本不知道从何下手&#xff1b;大家学习过程中大都不成体系&#xff0c;但面试的时候都上升到源码级别了&#xff0c;你不光要清楚了解Spring源码…

作者头像 李华
网站建设 2026/7/28 19:17:31

数据分析自学路线:Excel、SQL、Python、Tableau核心技能栈详解

很多同学想入门数据分析,但面对Excel、SQL、Tableau、Python这些工具,常常感到无从下手,网上资料要么太散,要么太深,很难形成体系化的学习路径。本文旨在为你梳理一条清晰、实用、可执行的数据分析自学路线,涵盖从数据处理、分析到可视化的核心技能栈,并提供可直接上手的…

作者头像 李华
网站建设 2026/7/28 19:17:00

ac自动机学习

模板&#xff1a;#include<bits/stdc.h> using namespace std; const int N500005; struct ac_automation {int trie[N][26];int e[N]; //字符串的结尾标记 int fail[N];int L,root;int newnode() //清空该节点下面所有子节点并得到一个新节点{for(int i0;i<26;i)t…

作者头像 李华
网站建设 2026/7/28 19:16:16

Palworld存档工具终极指南:轻松管理你的游戏世界

Palworld存档工具终极指南&#xff1a;轻松管理你的游戏世界 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools 你是否曾为Palworld存档文件无法直接…

作者头像 李华
网站建设 2026/7/28 19:15:05

企业知识库AI助手的日志分析与性能优化实践

1. 企业知识库AI助手的核心价值与挑战企业知识库AI助手正在成为数字化转型中的关键基础设施。这类系统通过自然语言处理技术&#xff0c;让员工能够像与人类专家对话一样&#xff0c;快速获取企业内部的流程文档、技术手册、产品资料等结构化知识。根据实际部署经验&#xff0c…

作者头像 李华
网站建设 2026/7/28 19:13:41

《运维》三、解析二级域名和配置https证书(运维4)

解析二级域名和配置https证书 一、解析二级域名(DNS 解析 DNSPod)1、打开腾讯云/阿里云2、找到 云解析 -> 域名解析列表 -> 点击要解析域名的解析操作3、点击添加记录比如原来主域名为mywebsite.com&#xff0c;子域名名字填写abc4、ping abc.mywebsite.com 测试是否添加…

作者头像 李华