基本概念
Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
(Generator 生产者,yield产出)
特征: function
关键字与函数名之间有一个星号
函数体内部使用yield
表达式,定义不同的内部状态
|
|
yield表达式:
由于 Generator 函数返回的遍历器对象,只有调用next
方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield
表达式就是暂停标志 。
yield只能在Generator函数里面有效
yield没有返回值,或者总是返回undefined,
next
方法可以带一个参数,该参数就会被当作上一个yield
表达式的返回值。(所以第一次使用next()方法传递参数是无效的,因为他表示的是上一个yield表达式的返回值)1234567891011121314function* foo(){var y = 2*(yield(x+1))var z= yield(y/3)return (x+y+3)}var a = foo(5);a.next() // Object{value:6, done:false} //返回yield后面式子的值a.next() // Object{value:NaN, done:false} //第二次运行next方法的时候不带参数,导致y的值等于2 * undefined(即NaN)a.next() // Object{value:NaN, done:true}var b = foo(5);b.next() // { value:6, done:false }b.next(12) // { value:8, done:false }b.next(13) // { value:42, done:true }yield
表达式如果用在另一个表达式之中,必须放在圆括号里面。1234567function* demo() {console.log('Hello' + yield); // SyntaxErrorconsole.log('Hello' + yield 123); // SyntaxErrorconsole.log('Hello' + (yield)); // OKconsole.log('Hello' + (yield 123)); // OK}yield
表达式用作函数参数或放在赋值表达式的右边,可以不加括号。1234function* demo() {foo(yield 'a', yield 'b'); // OKlet input = yield; // OK}
|
|
从语法角度看,如果
yield
表达式后面跟的是一个遍历器对象,需要在yield
表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*
表达式。1234567891011121314function* 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"如果
yield*
后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员。123456function* gen(){yield* ["a", "b", "c"];}var a = gen()a.next() //{value: "a", done: false}a.next() //{value: "b", done: false}实际上,任何数据结构只要有 Iterator 接口,就可以被
yield*
遍历。1234567let read = (function* () {yield 'hello';yield* 'hello';})();read.next().value // "hello"read.next().value // "h"
for…of循环
for...of
循环可以自动遍历 Generator 函数时生成的Iterator
对象,且此时不再需要调用next
方法。
|
|
|
|
Generator.prototype.return
可以传递参数返回给定的值,并且终结遍历Generator函数(done:flase)。
|
|
yield*表达式
用来在一个Generator函数foo里调用另外一个Generator函数bar,如果bar函数有return,那么foo函数里的yield*fn()就提供了上个函数bar的返回值
|
|