js中Generator函数的深入讲解


Posted in Javascript onApril 07, 2019

前言

Generator函数是es6提供的一种异步编程的解决方案,语法行为与传统函数完全不一样。

Generator函数有多种理解角度,从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。

行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了是状态机还是一个遍历器对象生成函数。 返回遍历器对象,可以依次遍历Generator函数内部的每一个状态。

下面话不多说了,来一起看看详细的介绍吧

语法上

首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

形式上

Generator 函数是一个普通函数,但是有两个特征。

 一是,function关键字与函数名之间有一个星号;
 二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。

调用上

Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)。我们必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行

function* helloWorldGenerator() {
 yield 'hello';
 yield 'world';
 return 'ending';
}

var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }

调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

yield表达式

yield表达式与return语句既有相似之处,也有区别。相似之处在于,都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield表达式。正常函数只能返回一个值,因为只能执行一次return;Generator 函数可以返回一系列的值,因为可以有任意多个yield。从另一个角度看,也可以说 Generator 生成了一系列的值,这也就是它的名称的来历(英语中,generator 这个词是“生成器”的意思)。

语法注意点:

1.yield表达式只能用在 Generator 函数里面

2.yield表达式如果用在另一个表达式之中,必须放在圆括号里面

3.yield表达式用作函数参数或放在赋值表达式的右边,可以不加括号。

例如:

function* demo() {
 foo(yield 'a', yield 'b'); // OK
 let input = yield; // OK
}

next 方法的参数

yield表达式本身没有返回值(就是说let a=yield ;会返回undefined),或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值 (注意,是表达式的返回值,例如 let a=yield.......... 参数会是a 的值并且会覆盖表达式之前的值)。

function* f() {
 for(var i = 0; true; i++) {
 var reset = yield i;
 console.log(reset);
 if(reset) { i = -1; }
 }
}

var g = f();

g.next()

js中Generator函数的深入讲解

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Firefox+FireBug使JQuery的学习更加轻松愉快
Jan 01 Javascript
基于PHP+Jquery制作的可编辑的表格的代码
Apr 10 Javascript
js 异步操作回调函数如何控制执行顺序
Dec 24 Javascript
jQuery的缓存机制浅析
Jun 07 Javascript
zeroclipboard 单个复制按钮和多个复制按钮的实现方法
Jun 14 Javascript
node.js中的fs.mkdir方法使用说明
Dec 17 Javascript
js中实现字符串和数组的相互转化详解
Jan 24 Javascript
vue.js组件之间传递数据的方法
Jul 10 Javascript
浅谈angular表单提交中ng-submit的默认使用方法
Sep 30 Javascript
vue动画效果实现方法示例
Mar 18 Javascript
微信小程序如何调用图片接口API并居中显示
Jun 29 Javascript
vue项目引入ts步骤(小结)
Oct 31 Javascript
巧妙运用v-model实现父子组件传值的方法示例
Apr 07 #Javascript
vue路由导航守卫和请求拦截以及基于node的token认证的方法
Apr 07 #Javascript
vue自定义指令directive的使用方法
Apr 07 #Javascript
浅谈express.js框架中间件(middleware)
Apr 07 #Javascript
详解vue中this.$emit()的返回值是什么
Apr 07 #Javascript
浅谈javascript中的prototype和__proto__的理解
Apr 07 #Javascript
javascrit中undefined和null的区别详解
Apr 07 #Javascript
You might like
腾讯QQ php程序员面试题目整理
2010/06/08 PHP
php中隐形字符65279(utf-8的BOM头)问题
2014/08/16 PHP
php内存缓存实现方法
2015/01/24 PHP
浅谈PHP中其他类型转化为Bool类型
2016/03/28 PHP
微信公众平台开发(五) 天气预报功能开发
2016/12/03 PHP
php实现的中文分词类完整实例
2017/02/06 PHP
thinkphp框架page类与bootstrap分页(美化)
2017/06/25 PHP
通过JAVAScript实现页面自适应
2007/01/19 Javascript
用JavaScript实现仿Windows关机效果
2007/03/10 Javascript
Extjs学习笔记之一 初识Extjs之MessageBox
2010/01/07 Javascript
window.open关于浏览器拦截问题分析及解决方法
2013/02/05 Javascript
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
js中style.display=""无效的解决方法
2014/10/30 Javascript
jquery.uploadify插件在chrome浏览器频繁崩溃解决方法
2015/03/01 Javascript
jQuery UI库中dialog对话框功能使用全解析
2016/04/23 Javascript
JavaScript基础心法 数据类型
2018/03/05 Javascript
Vue隐藏显示、只读实例代码
2018/07/18 Javascript
JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例
2018/07/23 Javascript
详解如何解决vue开发请求数据跨域的问题(基于浏览器的配置解决)
2018/11/12 Javascript
js定义类的方法示例【ES5与ES6】
2019/07/30 Javascript
在vue中使用vant TreeSelect分类选择组件操作
2020/11/02 Javascript
[02:27]2018DOTA2亚洲邀请赛趣味视频之钓鱼大赛 谁是垂钓冠军?
2018/04/05 DOTA
Python基于PycURL自动处理cookie的方法
2015/07/25 Python
pyqt5 获取显示器的分辨率的方法
2019/06/18 Python
弄懂这56个Python使用技巧(轻松掌握Python高效开发)
2019/09/18 Python
Python while循环使用else语句代码实例
2020/02/07 Python
Django和Ueditor自定义存储上传文件的文件名
2021/02/25 Python
详解CSS3浏览器兼容
2016/12/14 HTML / CSS
纯html5+css3下拉导航菜单实现代码
2013/03/18 HTML / CSS
手机端用rem+scss做适配的详解
2017/11/15 HTML / CSS
倩碧澳大利亚官网:Clinique澳大利亚
2019/07/22 全球购物
交通法规咨询中心工作职责
2013/11/27 职场文书
化妆师职业生涯规划书
2014/02/16 职场文书
财务人员的自我评价范文
2014/03/03 职场文书
村干部培训方案
2014/05/02 职场文书
2015年社区矫正工作总结
2015/04/21 职场文书