Generator函数语法解析

Generator函数是ES6提供的一种异步编程解决方案,语法与传统函数完全不同。以下会介绍一下Generator函数。

写下这篇文章的目的其实很简单,是想梳理一下自己对于Generator的理解,同时呢,为学习async函数做一下知识储备。

Generator函数

基本概念

yield表达式

next方法

next方法的参数

yield*表达式

与Iterator接口的关系

for...of循环

作为对象属性的Generator函数

Generator函数中的this

应用

基本概念

对于Generator函数(也可以叫做生成器函数)的理解,可以从四个方面:

形式上:Generator函数是一个普通的函数,不过相对于普通函数多出了两个特征。一是在function关键字和函数明之间多了'*'号;二是函数内部使用了yield表达式,用于定义Generator函数中的每个状态。

语法上:Generator函数封装了多个内部状态(通过yield表达式定义内部状态)。执行Generator函数时会返回一个遍历器对象(Iterator对象)。也就是说,Generator是遍历器对象生成函数,函数内部封装了多个状态。通过返回的Iterator对象,可以依次遍历(调用next方法)Generator函数的每个内部状态。

调用上:普通函数在调用之后会立即执行,而Generator函数调用之后不会立即执行,而是会返回遍历器对象(Iterator对象)。通过Iterator对象的next方法来遍历内部yield表达式定义的每一个状态。

写法上:*号放在哪里好像都可以也。看个人习惯吧,我喜欢第一种写法

function *gen () {} √ function* gen () {} function * gen () {} function*gen () {} yield表达式

yield,英文意思即产生、退让的意思,因此yield表达式也有两种作用:定义内部状态暂停执行

举一个栗子吧: )

function *gen () { yield 1 yield 2 return 3 } const g = gen() // Iterator对象 g.next() // {value: 1, done: false} g.next() // {value: 2, done: false} g.next() // {value: 3, done: true}

从上面代码中可以看出,gen函数使用yield表达式定义了两个内部状态。同时呢,也可以看出来,return语句只能有一个,而yield表达式却可以有多个。

执行gen函数之后,会返回一个遍历器对象,而不是立即执行gen函数。如果需要获取yield表达式定义的每个状态,需要调用next方法。

每调用一次next方法都会返回一个包含value和done属性的对象,此时会停留在某个yield表达式结尾处。value属性值即是yield表达式的值;done属性是布尔值,表示是否遍历完毕。

另外呢,yield表达式没有返回值,或者说返回值是undefined。待会会说明一下如何给yield表达式传递返回值。

需要注意的是,yield表达式的值,只有调用next方法时才能获取到。因此等于为JavaScript提供了手动的'惰性求值'(Lazy Evaluation)的功能。

一般情况下,Generator函数会结合yield表达式使用,通过yield表达式定义多个内部状态。但是,如果不使用yield表达式的Generator函数就成为了一个单纯的暂缓执行函数,个人感觉没什么意义...

function *gen () { console.log('凯斯') } window.setTimeout(() => { gen().next() }, 2000) // 不使用yield表达式来暂停函数的执行,还不如使用普通函数呢.. // 所以Generator函数配合yield表达式使用效果更佳

另外,yield表达式如果用在另一个表达式中,需要为其加上圆括号。作为函数参数和语句是可以不使用圆括号。

function *gen () { console.log('hello' + yield) × console.log('hello' + (yield)) √ console.log('hello' + yield '凯斯') × console.log('hello' + (yield '凯斯')) √ foo(yield 1) √ const param = yield 2 √ } next方法

yield表达式具有暂停执行的功能,而恢复执行的是next方法。每一次调用next方法,就会从函数头部或者上一次停下来的地方开始执行,直到遇到下一个yield表达式(return 语句)为止。同时,调用next方法时,会返回包含value和done属性的对象,value属性值可以为yield表达式、return语句后面的值或者undefined值,done属性表示遍历是否结束。

遍历器对象的next方法(从Generator函数继承而来)的运行逻辑如下

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

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

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

如果该函数没有return语句,则返回的对象的value属性值为undefined。

从上面的运行逻辑可以看出,返回的对象的value属性值有三种结果:

yield表达式后面的值

return语句后面的值

undefined

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzdfx.html