第一个next()调用的参数在哪里?

时间:2015-09-07 22:21:15

标签: javascript node.js generator ecmascript-6

我有一个简单的生成器函数

function *generate(arg) {
  console.log(arg)
  for(let i = 0; i < 3;i++) {
    console.log(yield i);
  }
}

然后我启动生成器并尝试在控制台中打印值:

var gen = generate('arg'); //doesn't print
gen.next('a'); // prints 'arg'
gen.next('b'); // prints 'b'
gen.next('c'); // prints 'c'
// ... nothing surprising later

来自第一个a来电的参数next()去了哪里?有没有办法在发电机功能中使用它?

这是Babel REPL,您可以在其中看到该结果。

2 个答案:

答案 0 :(得分:3)

next方法定义如下:

  

25.3.1.2 Generator.prototype.next ( value )

     

next方法执行以下步骤:

     
      
  1. g 成为值。
  2.   
  3. 返回GeneratorResume g )。
  4.   

GeneratorResume抽象操作在步骤10使用 value

  

25.3.3.3 GeneratorResume ( generator, value )

     

带有参数生成器和的抽象运算GeneratorResume   value执行以下步骤:

     
      
  1. genContext generator 的[[GeneratorContext]] internal slot的值。
  2.         

         
        
    1. 使用suspended value )作为操作的结果,恢复 genContext NormalCompletion评估   suspended它。让结果为恢复返回的值   计算。
    2.   

第一种可能性是使用yield(即"suspendedYield"州)暂停了评估。

其行为在14.4.14 Runtime Semantics: Evaluation中解释:

  

YieldExpression yield

     
      
  1. 返回GeneratorYieldCreateIterResultObject未定义,   的))。
  2.   

(类似于 YieldExpression yield AssignmentExpression

GeneratorYield抽象操作暂停生成器,如下所示:

  
      
  1. 设置 genContext 的代码评估状态,以便在使用Completion resumptionValue 恢复评估时   将执行以下步骤:

         
        
    1. 返回 resumptionValue
    2.   
    3. 注意:这将返回对最初调用此抽象操作的 YieldExpression 生产的评估。
    4.   
  2.   

因此,作为第二个next的参数传递的值将用作第一个yield表达式的返回值。并且作为第3个next的参数传递的值将用作第2个yield表达式的返回值。等等。

但是,生成器还有可能尚未启动(即"suspendedStart"状态)。

这是由GeneratorStart抽象操作完成的:

  
      
  1. 设置 genContext 的代码评估状态,以便在为execution context以下{{3}}恢复评估时   将执行以下步骤:
  2.   

但那些“后续步骤”不使用恢复值。

因此,作为第一个next的参数传递的值将被丢弃。

答案 1 :(得分:2)

不,你不能使用第一个值。如果您将代码更改为:

,这将是有益的
'use strict';
function *generate(arg) {
  console.log(arg)
  for(let i = 0; i < 3;i++) {
    console.log(yield i);
  }
  return 'done';
}

var gen = generate('arg');
console.log(gen.next('a'));
console.log(gen.next('b'));
console.log(gen.next('c'));
console.log(gen.next('d'));

当您实例化生成器时,它还没有开始执行,也没有记录任何内容。在第一个gen.next('a')上,您运行第一个产量,该产量通过生成器中的console.log(arg)然后执行yield 0。然后在调用者中获取console.log,然后获得{value: 0, done:false}等,直到完成迭代。总体输出如下:

arg
{ value: 0, done: false }
b
{ value: 1, done: false }
c
{ value: 2, done: false }
d
{ value: 'done', done: true }

最终done是返回值,如果省略生成器上的undefined,则为return