Generator
Generator函数是ES6提供的一种异步编程解决方案,Generator函数是一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
Generator的两个特征:
function
关键字与函数名之间有一个星号- 函数体内部使用
yield(产出)
语句,定义不同的内部状态
function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
yield语句
由于Generator函数返回的遍历器对象,只有调用next
方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield
语句就是暂停标志。
yield和return
相似:都能返回紧跟在语句后面的那个表达式的值
区别:
- 每次遇到
yield
,函数暂停执行,下一次再从该位置继续向后执行,而return
语句不具备位置记忆的功能 - 一个函数里面,只能执行一次(或者说一个)
return
语句,但是可以执行多次(或者说多个)yield
语句。
在使用for...of时自动遍历Generator函数,不需要调用next方法
yield*语句
如果在Generater函数内部,调用另一个Generator函数,默认情况下是没有效果的。这个就需要用到yield*
语句,用来在一个Generator函数里面执行另一个Generator函数。
function* bar() { yield 'x'; yield* foo(); yield 'y'; } // 等同于 function* bar() { yield 'x'; yield 'a'; yield 'b'; yield 'y'; } // 等同于 function* bar() { yield 'x'; for (let v of foo()) { yield v; } yield 'y'; } for (let v of bar()){ console.log(v); } // "x" // "a" // "b" // "y"