Javascript函数生成器参数

时间:2018-03-16 12:50:58

标签: javascript ecmascript-6

我正在从ES6(函数发生器)学习这个功能,我很难理解以下代码:

function* HelloGen2() {
  var a = yield 100;
  var b = yield a + 100;

  console.log(b);
}

var gen2 = HelloGen2();

console.log(gen2.next());     // {value: 100, done: false}
console.log(gen2.next(500));  // {value: 600, done: false}
console.log(gen2.next(1000)); // {value: undefined, done: true}

问题:

1:在第一个gen2.next()调用代码行var a = yield 100;时,是否在var a变量上设置了一些值?
   2:在每个gen2.next()中只有直到分号执行的行?
例如,在第二次调用gen2.next(500)中,行console.log(b);未执行 3:我不明白最后一行gen2.next(1000),b变量如何得到1000值?

3 个答案:

答案 0 :(得分:3)

yield xgenerator.next(y)之间的关系如下:

  • generator.next(y) 返回 {value: x, done: false}
  • yield x 评估为 y

此外,生成器函数在最初调用时不会开始执行。您可以将其视为构造函数。只有在调用generator.next()之后,实际的函数代码才会执行​​,直到第一个yield语句(或函数终止)。

在你的例子中:

  • var gen2 = HelloGen2()创建了生成器,但没有任何乐趣。
  • gen2.next()执行最多yield 100的功能,然后返回{value: 100...}
  • gen2.next(500)恢复功能执行,首先将yield语句评估为500(并立即将此值设置为a),然后继续执行yield a+100然后返回{value: 600...}
  • gen2.next(1000)恢复函数执行,首先将yield语句评估为1000(并立即将此值设置为b),然后继续执行直到终止,然后返回{{1} }。

最后{value: undefined, done: true}是函数而不是显式返回任何值的结果。

答案 1 :(得分:3)

使用协同程序时,理解这一点非常重要,虽然yieldnext是不同的关键字,但它们的作用基本相同。想象一下两个协同程序通过双向通信管道连接。两个

 Y = yield X

 Y = next(X)

执行相同的操作集:

  • 将X写入管道
  • 等待答案
  • 一旦答案出现,请从管道中读取并将其分配给Y
  • 继续执行

最初,主程序处于活动状态,生成器(示例中为gen2)正在等待侦听管道。现在,当您调用next时,主程序将一个虚拟值(null)写入管道,从而唤醒生成器。生成器执行yield 100,将100写入管道并等待。主要唤醒,从管道中读取100,记录并写入500。生成器唤醒,将500读入a等等。这是完整的流程:

    gen                   wait

main next()               null -> pipe
main                      wait

    gen                   pipe -> null
    gen yield 100         100 -> pipe
    gen                   wait

main                      pipe -> arg (100)
console.log(arg)          100
main next(500)            500 -> pipe
main                      wait

    gen a=                pipe -> a (500)
    gen yield a + 100     600 -> pipe
    gen                   wait

main                      pipe -> arg (600)
console.log(arg)          600
main next(1000)           pipe -> 1000
main                      wait

    gen b=                pipe -> b
    console.log(b)        1000
    gen (ended)           done -> pipe

main                      pipe -> arg (done)
console.log(arg)
main (ended)

基本上,为了理解生成器,你必须记住,当你指定或以某种方式使用yield/next的结果时,在右边和左边之间会有一个暂停(或者"生成&# 34;和"使用")部分。当你这样做

  var a = 5

这是立即执行的,而

 var a = yield 5

涉及=yield之间的暂停。这需要一些心理体操,与async工作流程非常相似,但是随着时间的推移,你会习惯这一点。

答案 2 :(得分:2)

  

问题:

     
      
  1. 在第一个gen2.next()调用代码行var a = yield 100;时,是否在var a变量上设置了一些值?
  2.   

目前尚未启动,gen2.next(500)的下次调用会获得500的值。在第一次调用时,该值仍为undefined

  
      
  1. 在每个gen2.next()中只有直到分号执行的行?
      例如,在第二次调用gen2.next(500)中,行console.log(b);未执行。
  2.   

右。该函数在最后一个yield语句后直接停止。

  
      
  1. 我不明白最后一行gen2.next(1000)b变量如何获得1000值?
  2.   

通过next()的调用,该函数在最后一站继续使用yield语句,该值将被移交并分配给b

执行console.log(b)并且函数在结束时退出,生成器的结果设置为{ value: undefined, done: true }



function* HelloGen2() {
    var a, b;
  
    console.log(a, b); // undefined undefined
    a = yield 100;
    console.log(a, b); //       500 undefined
    b = yield a + 100;

    console.log(b);    // 1000
}

var gen2 = HelloGen2();

console.log('#1');
console.log(gen2.next());     // { value: 100, done: false }
console.log('#2');
console.log(gen2.next(500));  // { value: 600, done: false }
console.log('#3');
console.log(gen2.next(1000)); // { value: undefined, done: true }
console.log('#4');

.as-console-wrapper { max-height: 100% !important; top: 0; }