使用for-of
由于Generator函数返回一个iterable
对象,所以我们可以使用for-of
循环来读取每一个生成的值。
我们基于前文谈到的Generator函数的例子,并写一个循环来读取其生成的值:
code/generators/use-for-of.js
function* myGenerator() {
let i = 0
while (i < 2) {
i += 1
yield i
}
}
const g = myGenerator()
for (const v of g) {
console.log(v)
}
上面的代码会输出1和2。
使用while循环
你还可以使用while
循环来遍历generator对象:
code/generators/use-while-loop.js
const g = myGenerator()
let next = g.next().value
while (next) {
console.log(next)
next = g.next().value
}
在上面的代码中,我们先获取第一个生成的值并把它赋值给next
变量,然后在while
循环中,依次把下一个生成的值赋值给变量next
。while
循环会一直运行,直到next
为undefined
为止,也就是Generator最后生成的值。
使用展开运算符和Array.from
因为generator对象是一个iterable
对象,所以你可以使用展开运算符...
来读取它的值:
code/generators/use-spread.js
function* myGenerator() {
let i = 0
while (i < 2) {
i += 1
yield i
}
}
const vals = [...myGenerator()] // -> [1, 2]
在上面的例子中,我们在一个数组中调用了Generator函数,并且使用扩展运算符解开其返回的iterable
对象,最后将得到的值[1, 2]
赋值给变量vals
。
除了扩展运算符,你还可以使用Array.from
方法来读取生成的值,并把结果放在一个数组中:
code/generators/use-array-from.js
function* myGenerator() {
let i = 0
while (i < 2) {
i += 1
yield i
}
}
const vals = Array.from(myGenerator()) // --> [1, 2]
在上面的代码中,我们首先调用了Generator函数,然后把它传递给了Array.from
,后者会读取生成的每一个值,并把它们存储在数组中,其结果为[1, 2]
。
值得注意的是,如果你遍历的generator对象的生成函数中包含了return
语句,那么像for-of
和展开运算符之类的内部遍历方法无法读取最后一个生成的值:
function* withReturn() {
yield 1
yield 55
return 250
yield 500
}
for (const v of withReturn()) {
console.log(v)
}
上面的代码会输出1,然后输出55,但是不会输出250。如果以你使用展开运算符也会得到同样的结果:
function* withReturn() {
yield 1
yield 55
return 250
yield 500
}
const vals = [...withReturn()]
console.log(vals)
上面的代码会输出[1, 55],并没有包含250。但是,如果你使用while
循环的话,我们能够获得包括return
语句返回的值在内的所有结果:
function* withReturn() {
yield 1
yield 55
return 250
yield 500
}
const g = withReturn()
let next = g.next().value
while (next) {
console.log(next)
next = g.next().value
}
while
循环获得了所有的结果,包含return
语句返回的值,它会打印出1,55,250。