一、Generator概述
1、Generator函数是一个普通函数,但是有以下几个特征:
function
关键字与函数名之间有一个星号 //一般星号紧挨function关键字- 函数体内部使用
yield
语句,定义不同的内部状态 //使用实例的next()方法可依次取得不同的状态 - 返回值是‘遍历器对象‘
- 返回值是本身Generator函数的一个实例
- 每一次调用都会产生新的‘遍历器对象‘
- 无论何种遍历方式 都只能遍历一次 //for...of||next()||...运算符 //只能被遍历一次
2、yield语句
- 遇到
yield
语句,就暂停执行后面的操作,并将紧跟在yield
后面的那个表达式的值,作为返回的对象的value
属性值 - 下一次调用
next
方法时,再继续往下执行,直到遇到下一个yield
语句 - 如果没有再遇到新的
yield
语句,就一直运行到函数结束,直到return
语句为止,并将return
语句后面的表达式的值,作为返回的对象的value
属性值 - 如果该函数没有
return
语句,则返回的对象的value
属性值为undefined
- yield语句不能用在普通函数中,否则会报错
- yield语句如果用在一个表达式之中,必须放在圆括号里面
- yield语句后面如果是一个函数,只用非匿名函数才会执行函数,否则只返回Function对象 //如下图:
3、与Iterator接口的关系
- Generator函数就是遍历器生成函数,因此可以把Generator赋值给对象的
Symbol.iterator
属性,从而使得该对象具有Iterator接口 - Generator函数执行后,返回一个遍历器对象。该对象本身也具有
Symbol.iterator
属性,执行后返回自身
4、测试如下:
二、next()方法的参数
1、next方法可以带一个参数,该参数就会被当作上一个yield
语句的返回值。
2、Generator函数从暂停状态到恢复运行,它的上下文状态(context)是不变的。通过next
方法的参数,就有办法在Generator函数开始运行之后,继续向函数体内部注入值。也就是说,可以在Generator函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。
三、for...of
1、for...of循环可以自动遍历Generator函数,且此时不再需要调用next
方法。
四、Generator.prototype.throw()
1、Generator函数返回的遍历器对象,都有一个throw
方法,可以在函数体外抛出错误,然后在Generator函数体内捕获
2、遍历器对象的throw
方法和全局的throw
命令
五、Generator.prototype.return()
1、Generator函数返回的遍历器对象,还有一个return
方法,可以返回给定的值,并且终结遍历Generator函数
2、如果return
方法调用时,不提供参数,则返回值的value
属性为undefined
3、如果Generator函数内部有try...finally
代码块,那么return
方法会推迟到finally
代码块执行完再执行。
六、yield*语句
1、用来在一个Generator函数里面执行另一个Generator函数 //将其展开成多个yield语句
2、yield*是for...of
的一种简写形式,完全可以用后者替代前者
3、如果yield*
后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员 //字符串也一样
4、任何数据结构只要有Iterator接口,就可以被yield*
遍历
5、yield*命令可以很方便地取出嵌套数组的所有成员。
function* iterTree(tree) { if (Array.isArray(tree)) { for(let i=0; i < tree.length; i++) { yield* iterTree(tree[i]); } } else { yield tree; } } const tree = [ ‘a‘, [‘b‘, ‘c‘], [‘d‘, ‘e‘] ]; for(let x of iterTree(tree)) { console.log(x); } // a // b // c // d // e
七、作为对象属性的Generator函数
八、Generator函数的this
1、Generator函数总是返回一个遍历器而不是this对象,ES6规定这个遍历器是Generator函数的实例,也继承了Generator函数的prototype
对象上的方法。
2、Generator函数也能跟new
命令一起用
3、可通过变通的方法访问generator函数的this对象 //依赖于原型对象,将this对象逐个添加到元原型对象
九、意义||作用
1、Generator与状态机
2、Generator与协程
十、应用
1、异步操作的同步化表达
2、控制流管理
3、部署iterator接口
4、作为数据结构