遍历Generator函数生成的值

使用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循环中,依次把下一个生成的值赋值给变量nextwhile循环会一直运行,直到nextundefined为止,也就是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。

用户头像
登录后发表评论