js生成器函数中的第一个next()是否始终执行到第一个yield之前?

时间:2018-10-16 00:46:11

标签: javascript generator

MDN建议“调用迭代器的next()方法时,将生成器函数的主体直到执行,直到第一个yield表达式为止”,我确实理解了以下示例:

function* logGenerator() {
  console.log(0);
  console.log(1, yield);
  console.log(2, yield);
  console.log(3, yield);
}

var gen = logGenerator();

gen.next(); // 0
gen.next('pretzel'); // 1 pretzel
gen.next('california'); // 2 california
gen.next('mayonnaise'); // 3 mayonnaise

但是,当我遇到另一个例子时,我很困惑:

const foo = function*() {
  yield 10;
  yield 20;
};

const bar = foo();
console.log(bar.next()); // {value: 10, done: false}

如果第一个next()仅在第一个收益率之前执行代码之前,则该值应未定义。如何获得第一笔收益 WITHIN 的价值?我在这里有点困惑。感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

您可以通过记录生成器每次生成的结果以及向yield表达式中添加值来查看发生了什么,并且可以看到生成器实际生成的结果(MDN示例不打扰这样做是因为它从未使用过产生的值,而只是演示了next()参数的工作方式。)

通常,您不会使用单个生成器来生成值,也不会通过next()参数来接收值,而仅使用一个生成器。如果产生值,则可以单独使用yield <expression>作为语句(类似于return),而不是通常在表达式中使用。如果它接收到值,则可以在表达式中不带参数的情况下使用yield。但是,正如您在修改后的示例中看到的那样,底层机制同时允许两者。您只需要跟踪混乱的执行顺序即可。

function* logGenerator() {
  console.log(0);
  console.log(1, yield 10);
  console.log(2, yield 20);
  console.log(3, yield 30);
}

var gen = logGenerator();

console.log("call 1 yielded", gen.next().value); // 0
console.log("call 2 yielded", gen.next('pretzel').value); // 1 pretzel
console.log("call 3 yielded", gen.next('california').value); // 2 california
console.log("call 4 yielded", gen.next('mayonnaise').value); // 3 mayonnaise

您第一次调用生成器是执行console.log(0);,然后开始执行console.log(1, yield 10)。但是当到达yield表达式时,next()会在实际调用console.log()之前返回该值。

下次调用生成器时,它将在中断处恢复,这将构造console.log()的参数。 yield 10表达式被next()的参数替换,因此它执行console.log(1, 'pretzel')

然后它开始执行console.log(2, yield 20),并且发生同样的事情-在调用20之前产生console.log()

MDN试图显示的是next()的参数仅在第二次调用时才有意义,因为当生成器恢复时,它会替换中断表达式中的yield的值。第一次调用时使用参数无效,因为没有可替换的中断表达式。