Generator理解

Generator 函数是 ES6 提供的一种异步编程解决方案,可以这么理解:

  1. 从语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
    执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
  2. 形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
function* helloWorldGenerator() {yield 'hello';yield 'world';return 'ending';
}var hw = helloWorldGenerator();

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

hw.next()
// { value: 'hello', done: false }hw.next()
// { value: 'world', done: false }hw.next()
// { value: 'ending', done: true }hw.next()
// { value: undefined, done: true }

上面的程序执行了四次next:

  1. 第一次调用,Generator 函数开始执行,直到遇到第一个yield表达式为止。next方法返回一个对象,它的value属性就是当前yield表达式的值hello,done属性的值false,表示遍历还没有结束。
  2. 第二次调用,Generator 函数从上次yield表达式停下的地方,一直执行到下一个yield表达式。next方法返回的对象的value属性就是当前yield表达式的值world,done属性的值false,表示遍历还没有结束。
  3. 第三次调用,Generator 函数从上次yield表达式停下的地方,一直执行到return语句(如果没有return语句,就执行到函数结束)。next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。
  4. 第四次调用,此时 Generator 函数已经运行完毕,next方法返回对象的value属性为undefined,done属性为true。以后再调用next方法,返回的都是这个值。

yield认识

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

(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。

(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。

(4)如果该函数没有return语句或者执行完return之后再运行next的时候,则返回的对象的value属性值为undefined,done为true。
需要注意,yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。
yield表达式如果用在另一个表达式之中,必须放在圆括号里面
yield表达式用作函数参数或放在赋值表达式的右边,可以不加括号。
yield放在表达式中的时候,let s =(yield 1+2),s其值将会是undefined,而1+2这个等于3的值将会作为next返回对象的value的值

next方法

yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。

这个参数就是解决了上面说的注意事项的最后一个,yield的返回值总是undefined,

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

yield* 表达式

如果在 Generator 函数内部,调用另一个 Generator 函数,默认情况下是没有效果的。
这个就需要用到yield*表达式,用来在一个 Generator 函数里面执行另一个 Generator 函数。

function* inner() {yield 'hello!';
}function* outer1() {yield 'open';yield inner();yield 'close';
}var gen = outer1()
gen.next().value // "open"
gen.next().value // 返回一个遍历器对象
gen.next().value // "close"function* outer2() {yield 'open'yield* inner()yield 'close'
}var gen = outer2()
gen.next().value // "open"
gen.next().value // "hello!"
gen.next().value // "close"

JavaScript的Generator理解使用相关推荐

  1. javascript之异步操作理解---回调函数,async,await以及promise对象

    javascript之异步操作理解---回调函数,async,await以及promise对象 概述 概述 写在前面:虽然平时做项目,但是发现自己写的代码还是很烂.最近接触了一个对性能要求比较高的项目 ...

  2. 【javascript】深入理解对象

    为什么80%的码农都做不了架构师?>>>    今天学习的主题是 JavaScript对象. 要创建一个JavaScript对象大家应该都觉得很简单,直接写上一行 var obj = ...

  3. 我对javascript对象的理解

    前言 JavaScript这门语言除了基本类型都是对象,可以说JavaScript核心就是对象,因此理解JavaScript对象及其种种特性至关重要,这是内功.本文介绍了我对es5对象,原型, 原型链 ...

  4. JavaScript面向对象——深入理解寄生组合继承

    JavaScript面向对象--深入理解寄生组合继承 之前谈到过组合继承,会有初始化两次实例方法/属性的缺点,接下来我们谈谈为了避免这种缺点的寄生组合继承 寄生组合继承: 思路:组合继承中,构造函数继 ...

  5. JavaScript面向对象——深入理解原型继承

    JavaScript继承--深入理解原型继承 原型继承 // 父类function School (name, address) {this.name = namethis.address = add ...

  6. 【Javascript】深入理解this作用域问题以及new/let/var/const对this作用域的影响

    理解this作用域 <javascript高级程序设计>中有说到: this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象调用时,t ...

  7. Javascript闭包简单理解

    Javascript闭包简单理解 原文:Javascript闭包简单理解 提到闭包,想必大家都早有耳闻,下面说下我的简单理解. 说实话平时工作中实际手动写闭包的场景并不多,但是项目中用到的第三方框架和 ...

  8. php generator 风雪,PHP 生成器Generator理解

    这篇文章介绍的内容是关于PHP 生成器Generator理解,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 转载整理自:寄凡.风雪之隅.PHP手册 生成器(Generator)可解决的 ...

  9. JavaScript之全面理解面向对象的JS

    今天看到一篇文章写得很好,对于像博主这种js一般级别的菜鸟很有帮助,博主秉着"好文要转"的原则收藏了这篇文章,简单排了下版,分享给大家,本文转自原文:http://www.ibm. ...

最新文章

  1. RedHat 关闭selinux
  2. 装饰者设计模式,简单代码实现
  3. 2017年11月01日普及组 I Got a Matrix!
  4. Python3实现TCP端口扫描器
  5. python matplotlib 绘图
  6. 常见的 Java 错误及避免方法
  7. spring cloud+dotnet core搭建微服务架构:Api网关(三)
  8. 通过Blender将PMX模型转为FBX导入Unity
  9. VALSE学习(十):图像去模糊-image deblurring
  10. python 存储数据到有向无环图寻找路径_Python 随即生成DAG(有向无环图)
  11. 计算机导论的计算题,计算机导论复习题(选择部分)汇总
  12. 携程瘫痪非偶然 国内互联网企业漠视数据管理
  13. 信息系统服务器维护,信息系统运行维护服务方案(IT运维服务方案)-20210729025444.pdf-原创力文档...
  14. STC15单片机-LED闪烁(定时器)
  15. Perl下载和安装Python下载和安装
  16. JTS Java空间几何计算、距离、最近点、subLine等 稳健的一比,持续更新中
  17. 谷歌浏览器旧版本下载地址
  18. 笔记本电脑右下角网络图标显示红叉
  19. 著名数学家龚升的论述揭示高中“函数近代严格定义” 有非常明显错误
  20. phpnow安装apache失败及phpnow绑定域名解决方法,网站发布到外网

热门文章

  1. 第14章4节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-装备ViewServer-端口转发 3...
  2. yum 快速搭建lnmp环境
  3. 生产环境故障处理之nginx缓存权限问题
  4. 记一次TIME_WAIT网络故障
  5. apache集成tomcat,并根据域名进行分发 屏蔽端口显示
  6. Linux Mint 13 root登录
  7. Angular路由--基本用法
  8. No package 'libpcre' found
  9. Android与JS混编(js调用android相机扫描二维码)
  10. 迭代3:UC1,UC2的2.1 业务建模 2.2 UC2用例模型 2.3 UC2补充性规格说明