你可以通过在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对象,但是其中的值为undefined
,done
为true
。这表明,没有可以再生成的值了。