【es6】中的Generator

news2024/11/25 6:29:37

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.coloradmin.cn/o/904245.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Go版]算法通关村第十三关青铜——数字数学问题之统计问题、溢出问题、进制问题

这里写自定义目录标题 数字统计专题题目&#xff1a;数组元素积的符号思路分析&#xff1a;无需真计算&#xff0c;只需判断负数个数是奇是偶复杂度&#xff1a;时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( 1 ) O(1) O(1)Go代码 题目&#xff1a;阶乘尾数0的个数思路分析&am…

字节实习半年小感悟

实习差不多半年了&#xff0c;快要答辩了。 从开始准备答辩到现在差不多四五十天的时间&#xff0c;虽然做需求和答辩交替进行&#xff0c;但PPT已经修改迭代六七个版本了。 以前总觉得这句话是一句非常感性非常搞笑的话&#xff1a;“xx的智慧如同天上的皓月&#xff0c;我不…

嵌入式设备的 Json 库基本使用

大家好&#xff0c;今天给介绍一款基于 C 语言的轻量级的 Json 库 – cJson。可用于资源受限的嵌入式设备中。 cJSON 是一个超轻巧&#xff0c;携带方便&#xff0c;单文件&#xff0c;简单的可以作为 ANSI-C 标准的 JSON 解析器。 cJSON 是一个开源项目&#xff0c;github 下…

【Linux取经路】探索进程状态之僵尸进程 | 孤儿进程

文章目录 一、进程状态概述1.1 运行状态详解1.2 阻塞状态详解1.3 挂起状态详解 二、具体的Linux操作系统中的进程状态2.1 Linux内核源代码2.2 查看进程状态2.3 D磁盘休眠状态(Disk sleep)2.4 T停止状态(stopped) 三、僵尸进程3.1 僵尸进程危害总结 四、孤儿进程五、结语 一、进…

【线性代数-3Blue1Brown】- 4 矩阵乘法与线性变换复合

飞书原文档&#xff1a; https://fvcs2dhq8qs.feishu.cn/docx/QRfNdiRAcoaSn0xLSIrcv1W0n9f?fromfrom_copylink

【教程】华南理工大学校园网登录抓包和协议模拟

每次手动登录特别麻烦&#xff0c;而且时不时断一下&#xff0c;因此搞个脚本让它定时监测、断开重连比较方便。这里不讲这个脚本怎么写&#xff0c;只记录一下登录时的抓包内容。 蒜了&#xff0c;直接上解析吧&#xff0c;也不复杂&#xff0c;相信大家一目了然。 目录 抓包…

Linux命令200例:tail用来显示文件的末尾内容(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…

Java开发面试题 | 2023

Java基础 接口和抽象类的区别&#xff1f;Java动态代理HashMap 底层实现及put元素的具体过程currenthashmap底层实现原理&#xff1f;map可以放null值吗&#xff0c;currenthashmap为什么不能放null值synchronze和reetrantlock区别&#xff1f;怎样停止一个运行中的线程&#…

WPS-RCE

版本&#xff1a; WPS Office 2023 个人版 < 11.1.0.12313 WPS Office 2019 企业版 < 11.8.2.12085 原理&#xff1a; Office 中的 WebExtension&#xff08;通常称为 Office 插件或 Office 应用程序&#xff09;是一种用于扩展 Microsoft Office 功能的技术。Office …

Nacos 无法注册服务

情况描述 Nacos服务搭建完成。 引入了Nacos的依赖。 <!-- SpringCloud Alibaba 服务管理 --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependen…

Linux之套接字UDP实现网络通信

Linux之套接字UDP实现网络通信 文章目录 Linux之套接字UDP实现网络通信1.引言2.具体实现2.1需要知道的套接字接口1.socket()2.bind()3.recvfrom()4.sendto() 2.2服务器端server.hpp2.3服务器端server.cc2.4客户端Client.cc 1.引言 ​ 套接字(Socket)是计算机网络中实现网络通信…

Java-类与对象(下)

访问限定符 类可以将数据以及封装数据的方法结合在一起&#xff0c;更符合人类对事物的认知&#xff0c;而访问权限用来控制方法或者字段能否直接在类外使用。 这里目前主要掌握private&#xff0c;default和public public&#xff1a;可以理解为一个人的外貌特征&#xff0c;…

金狮金狮鹏保宝点盾云等加密视频翻录录屏教程

这款软件采用独家方法特殊方式打开录屏工具&#xff0c;理论上通杀所有的检测进程的加密视频播放器的检测&#xff0c;不被检测。 使用方法很简单&#xff1a; 点击 打开录屏工具&#xff0c;就可以以特殊方式加载录屏工具。 然后就可以开始录屏了。 下载&#xff1a;spjm.lan…

在线HmacSHA1加密工具--在线获取哈希值又称摘要

具体请前往&#xff1a; 在线计算HmacSha1工具

0102垂直分片-jdbc-shardingsphere

1 前言 垂直分片分为垂直分库于垂直分表&#xff0c;但是实际应用中数据库表会根据业务需要提前做好规划&#xff0c;垂直分表的情况很少使用。但是随着业务增长&#xff0c;某些重点业务数据库压力增大&#xff0c;可能考虑需要考虑垂直分库的情况。 垂直分库&#xff0c;简…

22-组件通信

一. 什么是组件通信 组件通信&#xff0c;就是指 组件与组件 之间的数据传递 1. 组件的数据是独立的&#xff0c;无法直接访问其他组件的数据。 2. 想用其他组件的数据 -> 组件通信 二. 不同的组件关系 和 组件通信方案分类 组件关系分类: 1. 父子关系 2. 非父子关系 组件…

【Unity】制作一个简单的菜单栏页面并实现其功能

这是一个简单的菜单页面制作&#xff0c;接下来我们将制作一个完整的菜单页面&#xff0c;并且通过一定的代码去实现它对应的效果。这个主要的功能就是我们在游戏中如果想暂停一下或者重新开始&#xff0c;那么就要用到我们这个功能。接下来我们将实现在游戏中按ESC退出键可以调…

第6步---MySQL的控制流语句和窗口函数

第6步---MySQL的控制流语句和窗口函数 1.IF关键字 -- 控制流语句 SELECT IF(5>3,大于,小于);-- 会单独生成一列的 SELECT *,IF(score >90 , 优秀, 一般) 等级 FROM stu_score;-- IFNULL(expr1,expr2) SELECT id,name ,IFNULL(salary,0),dept_id FROM emp4;-- ISNULL() …

【C语言学习】数组

定义数组 <类型>变量名称[元素变量] 元素数量必须是整数 int a[10]; double b[20]; scanf("%d",&a[i]);//输入数组数组 数组是一种容器&#xff0c;特点为其中所有元素具有相同的数据类型&#xff1b; 一旦创建&#xff0c;不能改变大小&#xff1b; 数…

【C语言】什么是结构体内存对齐?结构体的大小怎么计算?

目录 1.结构体内存对齐 对偏移量的理解&#xff1a;​ 2.结构体的大小计算 2.1结构体中只有普通的数据类型的大小计算 2.2 结构体中有嵌套的结构体的大小计算 3.修改默认对齐数 4.为什么存在内存对齐? 这篇文章主要介绍结构体内存对齐和如何计算大小。 在学习结构体内存…