Generator函数是ES6提供的一种异步编程解决方案。语法行为与传统函数完全不同。Generator函数可以被理解为一种状态机,封装了多个内部状态。执行Generator函数会返回一个遍历器对象,可以一次遍历Generator函数内部的每一个状态。
Generator函数是一个普通函数,不同的是:
function
关键字与函数名之间有一个星号(*)- 函数体内部使用
yield
表达式,定义不同的状态(yield的意思为“产生”)
Generator函数的调用方式与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用Generator函数后,函数并不执行,返回的也不是函数的运行结果,而是一个指向内部状态的指针对象,也就是遍历器对象(Iterator)。
说到遍历器对象(Iterator),那就可以想到next()
方法。对于遍历器对象,必须调用next
方法,使得指针移向下一个状态。也就是说,每次调用next
方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield
表达式(或return
语句)为止。
Generator函数是分段执行的,
yield
表达式是暂停执行的标记,next
方法可以恢复执行。
例如,创建一个Generator方法:
1 | function * myGenerator() { |
获得迭代器对象:
1 | const g = myGenerator(); |
调用next
方法获得值:
1 | console.log(g.next()); // { value: 1, done: false } |
通过for...of
遍历迭代器:
1 | for (let i of g) { |
yield表达式
在Generator函数返回的遍历器对象,只有next
方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数,yield表达式就是暂停标志。遍历器对象的next
方法的运行逻辑:
- 遇到
yield
表达式,就暂停执行后面的操作,并将紧跟在yield
后面的那个表达式的值,作为返回对象的value
属性值。 - 下一次调用
next
方法,再继续往下执行,直到遇到下一个yield
表达式。 - 如果没有再遇到新的
yield
表达式,就一直运行到函数的结束,直到return
语句为止,并将return
语句后面的表达式的值作为返回对象的value
属性值 - 如果该函数没有
return
语句,则返回对象的value
属性值为undefined
。
注意:**yield
表达式后面的表达式,只有当调用next
方法、内部指针指向该语句时才会执行。**
Generator函数也可以不用yield
表达式,这时就编程了一个单纯的暂缓执行函数;另外,yield
表达式只能在Generator函数里面使用,用在其他地方都会报错。
next方法的参数
yield
表达式本身没有返回值,或者说总是返回undefined
。next
方法可以带一个参数,该参数会被当做上一个yield
表达式的返回值:
1 | function * myGenerator() { |
调用第二个next
的时候,i的值为1,此时Generator函数执行暂停在yield
这里,调用第三个next
的时候,给next
传入值为true,等于上一个yield i
表达式返回的值为true,这时候程序继续执行循环,先将i重置为-1,然后执行自增,运行到yield
的时候i的值为1.
Generator。prototype.thrwo()
Generator函数返回的遍历器对象,都有一个throw
方法,可以在函数体外抛出错误,然后在Generator函数体内捕获。
1 | function * myGenerator() { |
遍历器对象连续抛出两个错误,第一个错误被Generator函数体内的catch
语句捕获,第二次抛出错误的时候,由于Generator函数体内部的catch
语句已经执行过了,不会再捕捉这个错误,所以这个错误被抛出了Generator函数体,被函数体外的catch
语句捕获。
注意:throw方法抛出的错误要被内部捕获,前提是必须至少执行过一次next
方法。
一旦Generator执行过程中抛出错误,就不会再执行下去了。如果此后还调用next
方法,将返回一个{value: undefined, done: ture}
对象。即JavaScript引擎认为这个Generator已经运行结束了。
Generator.prototype.return()
Generator函数的遍历器对象中还有一个return
方法,可以返回给定的值,并且终结遍历Generator函数。例如:(Generator还使用上面的)
1 | const g = myGenerator(); |
如果return
方法调用时不提供参数,则返回的value
为undefined
.
ES6基础语法是用到什么就去深入了解下,在用的过程中加深理解。如果用不到只是去看文档的话,一个是看不进去,一个是看完了也很快就忘记了。这样在用的过程中去看文档同时进行笔记记录,会理解更深,也更难被忘记。
这个笔记只是学习了简单的使用,看文档上有很多复杂的使用,一般也用不上,如果真的用到了,再来补全。