Generator函数定义

  1. function关键字与函数名之间有一个*
  2. 函数体内部使用yield表达式,定义不同的内部状态

调用Generator函数时,实际上并不会执行,而是返回一个指向内部状态的对象。

通过执行Generator函数的next方法,来遍历函数内部的状态,同时使内部指针移向下一个状态(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 }

next方法和yield表达式

yield表达式表示暂停,返回一个包含valuedone的对象。valueyield表达式的值,done表示是否遍历结束

没调用一次next方法,执行到yield表达式为止。如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。如果该函数没有return语句,则返回的对象的value属性值是undefined

带参数的next方法

yield表达式本身返回undefinednext方法的参数会被当成上一个yield表达式的的返回值

function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
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 }

第一个a.next(),到yield(x + 1)暂停,值为6 第二个a.next(),到yield(y /3)暂停,next不带参数,上一个yield表达式的值(yield(x + 1)undefined),所以值为NaN 第三个a.next(),z为undefined的,值为NaN

第一个b.next(),到yield(x + 1)暂停,值为6 第二个b.next(12),到yield(y /3)暂停,next带参数,上一个yield表达式的值(yield(x + 1)12),y = 24所以值为8 第三个b.next(13),到return (x + y + z)暂停,next带参数,上一个yield表达式的值(yield((y /3)13),y = 24, z = 13值为42

for of 循环

for…of循环可以自动遍历Generator函数时生成的Iterator对象,但不会返回done属性为 true的对象

yield* 表达式

function* 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"

function* outer2() {
  yield 'open'
  yield* inner()
  yield 'close'
  yield ['a','b','c']
  yield* ['a','b','c']
}

var gen = outer2()
gen.next().value // "open"
gen.next().value // "hello!"
gen.next().value // "close"
gen.next().value // 数组对象
gen.next().value // "a"

使用了yield*后,返回遍历器对象(或数组)的内部值。