【es6】中的Generator

Generator

  • 一、Generator 是什么?
    • 1.1 与普通函数写法不一样,有两个不同
  • 二、Generator 使用
    • 2.1 书写方法
  • 三、yield语句
    • 3.1 yield和return
    • 3.2 注意事项
    • 3.3 yield*语句
    • 3.4 yield*应用
  • 四、next方法
    • 4.1参数
  • 总结


一、Generator 是什么?

Generator 函数是 ES6 提供的一种异步编程解决方案,最大特点交出函数的执行权。

和普通函数不一样的是必须调用next()才会执行函数。

1.1 与普通函数写法不一样,有两个不同

  • function与函数名之间有个(*)号;
    不同于普通函数,可暂停执行,所以加*区别。
  • Generator 函数体内部使用yield语句,可以定义不同的内部状态,其实就是数据不同。
    函数内部的状态,就是函数内部的值,它在不同的时候是不一样的。

本质上整个Generator函数就是一个封装的异步任务,或者说是异步任务的容器。
yield的命令是异步不同阶段的分界线,有时把yield的当成return。

二、Generator 使用

2.1 书写方法

  1. 函数名和方法中间有个 *号,但没规定放置的位置,一般跟在function后面;
  1. 调用Generator 函数,函数并不执行,返回的是一个指向内部状态指针的对象(遍历器对象)
function* test(){let n = 1;yield n;yield++n;yield--n;return n;
}let t = test();
console.log(t);  //test {<suspended>}

返回的是一个对象,并且有next, return,throw方法
在这里插入图片描述

  1. 想打印值,必须调用next方法,使指针下一个状态。也就是每次调用都从上一个指针状态(yield)开始,遇到下一个yield或return语句为止。也就是一段段段执行,yield暂停,next继续执行。

下面调用6次,一个yield一个状态。返回一个对象,value代表值,done代表是否遍历结束(true结束,false未结束)

done为true已经代表函数结束,再打印几次值都为undefined

console.log(t.next());  //{value: 1, done: false}
console.log(t.next());  //{value: 2, done: false}
console.log(t.next());  //{value: 1, done: false}
console.log(t.next());  //{value: 1, done: true}
console.log(t.next());  //{value: undefined, done: true}
console.log(t.next());  //{value: undefined, done: true}

三、yield语句

yield语句就是暂停标志。

3.1 yield和return

相同点:

  • 都能返回后面表达式的值。

不同点:

  • yield的函数暂停执行时,下一次会从该位置继续向后执行,并且一个函数可有多个yield语句。
  • return返回就相当于结束函数,一个函数只有一个return。

3.2 注意事项

  1. yield后面n+1不会执行,只有调用next方法才会执行。
function* test() {let n = 1;yield n + 1;console.log(n);
}
test();   //此时打印是空白的//必须调用next方法才会执行
console.log(test().next());  //{value: 2, done: false}

2.可以不用yield,但是必须调用next方法才会执行

function* test() {let n = 1;console.log(n);
}
let t = test();
console.log(t.next());
  1. yield语句不能用在普通函数中。
function test() {yield 1;
}
console.log(test());  // Unexpected number

3.3 yield*语句

Generator 函数内部调用另一个Generator 函数,默认情况无效。

function* A(){yield 1;yield 2;
}
function* B(){yield 3;A();yield 4;
}
for(let i of B()){console.log(i)
}
//3
//4

虽然在B函数中调用了A(),但只能打印出3,4。如果想要调用,就要在前面使用yield*语句。

function* A(){yield 1;yield 2;
}
function* B(){yield 3;yield* A();yield 4;
}
for(let i of B()){console.log(i)
}
//3
//1
//2
//4

yield*是for…of…的一种简写形式,我们知道for…of…可以遍历出具有iterator接口的数据结构(数组,类数组对象,字符串,nodelist等)

3.4 yield*应用

  1. 数组扁平化
let a = [1,[1,2],[1,2,3]]
function* iterTree(arr){if(Array.isArray(arr)){for(let i = 0;i<arr.length;i++){yield* iterTree(arr[i]);}}else{yield arr;}	
}
for(let i of iterTree(a)){console.log(i)
}
  1. 遍历完全二叉树
// 构建树
function Tree(left,middle,right){this.left = left;this.middle = middle;this.right = right;
}
// 中序遍历函数
function* inorder(t){if(t){yield* inorder(t.left);yield t.middle;yield* inorder(t.right);}
}
// 生成二叉树
function make(array){if(array.length == 1) return new Tree(null,array[0],null);return new Tree(make(array[0]),array[1],make(array[2]));
}
let tree = make([[['a'],'b',['c']],'d',[['e'],'f',['g']]]);
// 遍历二叉树
var result = [];
for(let node of inorder(tree)){result.push(node);
}
console.log(result)   //['a', 'b', 'c', 'd', 'e', 'f', 'g']

四、next方法

next方法是使指针指向下一个状态。除了for…of遍历出来,必须调用next才能打印出yield值。

4.1参数

yield语句本身没有返回值,或者总返回undefined。next方法可以带一个参数,这个参数会被当上一个yield语句的返回值。

function* test(x) {var a = yield x-1;var b = yield (a+2);return a+b;
}
let t = test(4);
console.log(t.next())     //{value: 3, done: false}
console.log(t.next(10))   //{value: 12, done: false}
console.log(t.next(4))    //{value: 14, done: true}

第一步:传个4进去,x-1=3,打印出来为3
第二步:传个10进去,这个参数会被当上一个yield语句的返回值,也就是a的值为10,a+2,打印出来为12。
第三步:传个4进去,上一个参数b的值为4,a的值为之前的10,a+b为14。


总结

Generator 函数是一种异步编程解决,可以更好的控制函数执行。其中yield是同步的,调用next()才能打印出值。

函数返回的是一个对象,而next方法返回的也是一个对象,其中有value(值),done(是否遍历完)。

一个next对应一个yield语句,当最后done为true时,再调用next方法,值都是undefined。全部遍历可使用for…of,其原理还是数据结构内部有iterator接口。

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

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

相关文章

[JavaWeb]【一】入门JavaWeb开发总概及HTML、CSS、JavaScript

目录 一 特色 二 收获​编辑 三 什么是web? 四 网站的工作流程 五 web网站的开发模式​编辑 六 web开发课程学习安排 七、初始web前端 八 HTML、CSS 8.1 什么是HTNL\CSS(w3cschool) 8.2 HTML快速入门 8.3 VS Code开发工具 8.3.1 插件 8.3.2 主题&#xff08;改变颜色&…

【C++】做一个飞机空战小游戏(八)——生成敌方炮弹(rand()和srand()函数应用)

[导读]本系列博文内容链接如下&#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞…

solidwords(5)

我们打算从上面画出总体&#xff0c;再从上面、侧面切除 最后成品

blender 发射体粒子

发射体粒子的基础设置 选择需要添加粒子的物体&#xff0c;点击右侧粒子属性&#xff0c;在属性面板中&#xff0c;点击加号&#xff0c;物体表面会出现很多小点点&#xff0c;点击空格键&#xff0c;粒子会自动运动&#xff0c;像下雨一样&#xff1b; bender 粒子系统分为两…

抖音火山引擎推出免费域名DNS和公共DNS服务

抖音旗下的云计算服务火山引擎最近推出了"TrafficRoute DNS 套件"服务&#xff0c;其中包括两款产品&#xff0c;对软希网来说非常有用。 1.域名DNS&#xff1a; 这是一个用于网站域名的DNS服务&#xff0c;可以加速域名解析速度&#xff0c;从而提升网站的速度。如…

【3Ds Max】挤出命令的简单使用(实现二维变三维)

简介 在3ds Max中&#xff0c;"挤出"&#xff08;Extrude&#xff09;是一种常用的建模操作&#xff0c;用于在平面或曲面上创建立体几何形状。以下是使用3ds Max中的挤出命令的基本步骤&#xff1a; 创建基本几何形状&#xff1a; 在3ds Max中创建一个基本的几何形…

自动驾驶——车辆动力学模型

/*lat_controller.cpp*/ namespace apollo { namespace control {using apollo::common::ErrorCode;//故障码 using apollo::common::Status;//状态码 using apollo::common::TrajectoryPoint;//轨迹点 using apollo::common::VehicleStateProvider;//车辆状态信息 using Matri…

Kotlin实战之获取本地配置文件、远程Apollo配置失败问题排查

背景 Kotlin作为一门JVM脚本语言&#xff0c;收到很多Java开发者的青睐。 项目采用JavaKotlin混合编程。Spring Boot应用开发&#xff0c;不会发生变动的配置放在本地配置文件&#xff0c;可能会变化的配置放在远程Apollo Server。 问题 因为业务需要&#xff0c;需要增加一…

MybatisPlus整合p6spy组件SQL分析

目录 p6spy java为什么需要 如何使用 其他配置 p6spy p6spy是一个开源项目&#xff0c;通常使用它来跟踪数据库操作&#xff0c;查看程序运行过程中执行的sql语句。 p6spy将应用的数据源给劫持了&#xff0c;应用操作数据库其实在调用p6spy的数据源&#xff0c;p6spy劫持到…

mysql中的窗口函数

MySQL中的窗口函数&#xff08;Window Functions&#xff09;是一种用于在查询结果集内执行计算的功能。窗口函数可以在查询中进行分析和聚合操作&#xff0c;而无需将查询结果分组。它们可以用于计算排名、行号、累积值等各种分析操作。窗口函数通常与OVER子句一起使用&#x…

亿赛通电子文档安全管理系统任意文件上传漏洞复现

0x01 产品简介 亿赛通电子文档安全管理系统&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资产&…

AI 绘画Stable Diffusion 研究(十)sd图生图功能详解-精美二维码的制作

免责声明: 本案例所用安装包免费提供&#xff0c;无任何盈利目的。 大家好&#xff0c;我是风雨无阻。 为了让大家更直观的了解图生图功能&#xff0c;明白图生图功能到底是干嘛的&#xff0c;能做什么事情&#xff1f;今天我们继续介绍图生图的实用案例-精美二维码的制作。 对…

第 7 章 排序算法(3)(选择排序)

7.6选择排序 7.6.1基本介绍 选择式排序也属于内部排序法&#xff0c;是从欲排序的数据中&#xff0c;按指定的规则选出某一元素&#xff0c;再依规定交换位置后达到排序的目的。 7.6.2选择排序思想: 选择排序&#xff08;select sorting&#xff09;也是一种简单的排序方法…

stm32_ADC电源、通道、工作模式

0、ADC功能框图 1、ADC的电源 1.1、工作电源 VSSAVSS&#xff0c;VDDAVDD&#xff0c;简单来说&#xff0c;通常stm32是3.3V&#xff0c;ADC的工作电源也是3.3V&#xff1b; 1.2、参考电压 VREF和VREF-并不一定引出&#xff0c;取决于封装&#xff0c;如果没有引出则VREF连接到…

MyBatis入门配置及CURD实现

目录 一、MyBatis简介 1. 什么是 MyBatis ? 2. MyBatis的特性 3. 什么是持久层框架&#xff1f; 二、MyBatis环境配置 2.1 创建maven工程 2.2 导入相关pom依赖 2.3 导入jdbc配置文件 2.4 Mybatis相关插件安装 3.5 Mybatis-cfg.xml 核心配置 2.6 引入Log4j2日志文件…

Pycharm与Anaconda Python的开发环境搭建

目录 一&#xff1a;下载 二&#xff1a;安装python 三&#xff1a;设置Pycharm 一&#xff1a;下载 下载Anaconda&#xff1a; Anaconda | The World’s Most Popular Data Science Platform 安装好以后&#xff0c;设置一下环境变量&#xff1a; 打开命令行&#xff0c…

Maven高级

目录 一、分模块开发与设计 1. 分模块开发的意义 2. 分模块开发&#xff08;模块拆分&#xff09; &#xff08;1&#xff09;创建Maven模块 &#xff08;2&#xff09;书写模块代码 &#xff08;3&#xff09;通过maven指令安装模块到本地仓库&#xff08;install指令&…

记录:win10物理机ping不通虚拟机上的docker子网(已解决)

【说明】 windows10&#xff1a;已关闭防火墙 linux发行版本&#xff1a;centos7.9&#xff08;已禁用SElinux、已关闭防火墙&#xff09; 虚拟机软件&#xff1a;VMware Workstation 17 虚拟机网络模式&#xff1a;NAT模式 docker版本&#xff1a;20.4.5 docker网络模式…

一百六十一、Kettle——Linux上安装的kettle9.2开启carte服务(亲测、附流程截图)

一、目的 在Linux上安装好kettle9.2并且连接好各个数据库后&#xff0c;下面开启carte服务 二、实施步骤 &#xff08;一&#xff09;carte服务文件路径 kettle的Linux运行的carte服务文件是carte.sh &#xff08;二&#xff09;修改kettle安装路径下的pwd文件夹里的服务器…

华为将收取蜂窝物联网专利费,或将影响LPWAN市场发展

近日&#xff0c;华为正式公布了其4G和5G手机、Wi-Fi6设备和物联网产品的专利许可费率&#xff0c;其中包含了长距离通信技术蜂窝物联网。作为蜂窝物联网技术的先驱&#xff0c;华为是LTE Category NB (NB-IoT)、LTE Category M和其他4G物联网标准的主要贡献者。 在NB-IoT领域…