ES6生成器:首先调用next()

时间:2016-09-27 19:20:53

标签: javascript ecmascript-6

我试图了解如何使用ES6 Generator功能。除了这个关于在传递参数时进行空的next()函数调用的概念时,它似乎非常简单。这是我从Mozilla文档中引用的代码。

function* logGenerator() {
  console.log(yield);
  console.log(yield);
  console.log(yield);
}

var gen = logGenerator();

// the first call of next executes from the start of the function
// until the first yield statement

gen.next();
gen.next('pretzel'); // pretzel
gen.next('california'); // california
gen.next('mayonnaise'); // mayonnaise

根据我的理解,代码只执行到第一个yield语句,因此没有返回任何内容,然后第二次调用next(),代码执行到包含第一个yield行的第二个yield因此pretzel被记录到控制台。

如果是这种情况,在下面提到的代码中,0如何在next()的第一次调用中登录?我在这里遗漏了一些东西:(

function* idMaker() {
  var index = 0;
  while (index < 3)
    yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined

参考:Mozilla Documentation

3 个答案:

答案 0 :(得分:6)

嗯,发电机功能很特别。它们可以在执行过程中多次接受和返回值,而“普通”函数只能接受一组固定的参数,并返回单个值。在您的第一个示例中,它们用于将数据传递给生成器(多次传递参数),而在第二个示例中则反过来(多次返回值)。

考虑这个例子:

function* foo() {
    console.log("before a");

    var a = (yield 123);

    console.log("after a");

    yield (a * 2);

    console.log("end of function");
}

var bar = foo();

var x = bar.next(); // Runs until the first yield, prints 'before a'.
console.log(x.value); // 123
var y = bar.next(4); // Runs until the second yield, so prints 'after a'. 
console.log(y.value); // 8
var z = bar.next(); // prints 'end of function'.
console.log(z.done); // true

我们没有传递第一个next()调用的数据,让它一直运行到第一个yield语句。由于yield 123,调用的结果(x.value)为123.下次我们使用next()作为参数值调用4时,我们会填充局部变量{{1} }在生成器函数内部。代码执行到下一个a语句并返回yield的结果。

有关8代替0的解释,请参阅另一个答案。

答案 1 :(得分:3)

我认为你遇到的是后增量运算符的行为,即index++。如果您将其更改为预增量运算符,即++index,它将按照您期望的方式运行。

不同之处在于,在评估表达式之后,后递增将向index 添加1。在评估表达式之前,预增量将向index添加1,我认为这是您的目标。

答案 2 :(得分:0)

  

根据我的理解,代码只执行到第一个yield语句,因此不返回任何内容

在Mozilla的例子中,&#34;产生&#34;所有返回SOMETHING,他们返回undefined。这就像是&#34;返回&#34;在它之后没有任何东西,这也&#34;返回&#34;未定义。

这里特别的是,因为这是一个生成器函数,所以返回/收益发生在log()-statement的MIDDLE中。它们会在&#34;产生&#34; -statement STARTS EXECUTING。这意味着他们会跳出来#34;当前函数在log()语句完成之前,因此在第一次调用时没有任何内容到达控制台。换句话说,第一次收益导致函数*跳出&#34;跳出&#34;在log-statement获得执行机会之前。

当你打电话给第二个next()时,执行会从上次停止的时间开始继续执行,但是使用术语&#39; yield&#39;现在是作为参数传递给next()的东西。因此,log-statement现在继续并打印该值。

获得收益的棘手部分是这个&#34;瞬间&#34;冻结和下一个下一个()从上一次冻结的完全相同的点继续但是与术语“屈服”相对应。现在具有作为参数传递给next()的值。如果在某些语句(如log(yield))内发生yield,则冻结在contains语句能够执行之前发生。

或者换句话说,我觉得棘手的部分(而且我为什么重复自己这很棘手)是yield-statement导致函数在yield-statement完成之前返回。它将仅在下一个next()上完成,具有&#34; yield&#34;的值。变成对next()的调用的参数。

你的例子的不同之处在于你的log()-statements都发生在生成器函数的外面,在Mozilla的例子中它们发生在它里面。因此,您的logs()将使用从next()调用获得的值执行。由于您的logs()发生在生成器之外,因此您的所有log()语句都不会在中间被中断。