每周三集前端免费视频
每年帮助超100万前端爱好者学习

ES6学习:Generator函数详解

一、Generator函数简介:

基本概念

Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。对于Generator函数有多种理解角度。从语法上,首先可以把它理解成一个状态机,封装了多个内部状态。执行Generator函数会返回一个遍历器对象。也就是说,Generator函数除了是状态机,还是一个遍历器对象生成函数。返回遍历器对象,可以依次遍历Generator函数内部的每一个状态。

形式上,Generator函数是一个普通函数,但是有两个特征:

  1. function命令与函数名之间有一个星号。
  2. 函数体内部使用yield语句定义不同的内部状态。

上面的代码定义了一个Generator函数-helloWorldGenerator,它内部有两个yield语句“hello”和“world”,即该函数有3个状态:hello、world和return语句(结束执行)。

Generator函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用Generator函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是遍历器对象(Iterator Object)。

ES6没有规定function关键字与函数名之间的星号写在哪个位置。所以下面的写法都能通过。

yield语句

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

遍历器对象的next方法的运行逻辑如下。

  1. 遇到yield语句就暂停执行后面的操作,并将紧跟在yield后的表达式的值作为返回的对象的value属性值。
  2. 下一次调用next方法时再继续往下执行,直到遇到下一条yield语句。
  3. 如果没有再遇到新的yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值作为返回的对象的value属性。
  4. 如果该函数没有return语句,则返回的对象的value属性值为undefined。

需要注意的是,yield语句后面的表达式,只有当用next方法、内部指针指向该语句时才会执行,因此等于为JavaScript提供个了手动的“惰性求值”的语法功能。

上面的代码中,yield后面的表达式123+456不会立即求值,只会在next方法将指针移到这一句时才求值。

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

Generator函数可以不用yield语句,这时就变成了一个单纯的暂缓执行函数。

上面的代码中,函数f如果是普通函数,在为变量generator赋值时就会执行。但是函数f是一个Generator函数,于是就变成只有调用next方法时才会执行。

与Iterator接口的关系

任意一个对象的Symbol.iterator方法等于该对象的遍历器对象生成函数,调用该函数会返回该对象的一个遍历器对象。

遍历器对象本身也有Symbol.iterator方法,执行后返回自身。

上面的代码中,gen是一个Generator函数,调用它会生成一个遍历器对象g。它的Symbol.iterator属性也是一个遍历器对象生成函数,执行后返回它自己。

 

 

未经允许不得转载:技术胖-胜洪宇关注web前端技术 » ES6学习:Generator函数详解
分享到: 更多 (0)

评论 抢沙发