创建Generator

你可以通过在function关键字后面放置一个*号来创建Generator函数:

function* myGenerator() {
  //...
}

接下来,在Generator函数体中,我们可以通过yield表达式生成值:

code/generators/simple.js

function* simpleGenerator() {
  yield 1
  yield 5
}
const g = simpleGenerator()
const v1 = g.next().value // --> 1
const v2 = g.next().value // --> 5
const v3 = g.next().value // --> undefined

我们甚至定义一个无限循环来生成值:

code/generators/inf-loop.js

function* myGenerator() {
  let i = 0
  while (true) {
    i += 1
    yield i
  }
}

如果是正常函数的话,它就会限于一个死循环。但由于它是一个Generator函数,我们可以使用它返回的Generator对象上的next方法来获取生成的值:

const g = myGenerator()
const v1 = g.next() // --> { value: 1, done: false }
const v2 = g.next() // --> { value: 2, done: false }
const v3 = g.next() // --> { value: 3, done: false }
// and so on...

本质上,我们每一次调用next方法就是重新进入和退出Generator函数,而每次进入的点就是我们上次退出的点。注意i的值是如何被“记住”的。

现在,我们修改一下上面的代码,让Generator函数停止生成值。我们让Generator函数不再生成大于2的值:

function* myGenerator() {
  let i = 0
  while (true) {
    i += 1
    if (i > 2) {
      return
    }
    yield i
  }
}

或者,把判断条件移到while上,以此简化代码:

code/generators/inf-loop-terminate.js

function* myGenerator() {
  let i = 0
  while (i < 2) {
    i += 1
    yield i
  }
}

现在,如果我们读取生成的值,我们只能获取两个值:

const g = myGenerator()
const v1 = g.next() // --> { value: 1, done: false }
const v2 = g.next() // --> { value: 2, done: false }
const v3 = g.next() // --> { value: undefined, done: true }

注意,如果在第二个值之后,再次调用next,我们依然可以获得一个Generator对象,但是其中的值为undefineddonetrue。这表明,没有可以再生成的值了。

用户头像
登录后发表评论