为什么javascript生成器函数的yield语句返回.next()的参数?

时间:2017-08-15 22:12:44

标签: javascript yield

我偶然发现了generator functions on MDN,令我困惑的是以下示例:

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语句是console.log的参数,返回传递给生成器的.next()方法的参数。是否发生这种情况是因为空yield必须返回.next()方法的第一个参数的值?

我还尝试了一些例子,似乎证实了上述陈述:

gen.next(1,2,3); // the printed value is 1, the 2 and 3 are ignored
// and the actual yielded value is undefined

还有办法在生成器函数体内访问.next()方法的其他参数吗?

我注意到的另一件事是,当yield语句将这些值返回到console.log时,它们实际上不会作为生成器的输出产生。我必须说我觉得很困惑。

3 个答案:

答案 0 :(得分:3)

好问题。我认为在.next()方法上阅读MDN是最有帮助的。您可以在生成器函数本身中定义要传递的值(即yield 1),或者通过next()

之类的内容通过gen.next(1)传递值

next()方法本身返回一个Object,其属性为value,布尔值为done,表示生成器函数是否完整(即可用输出已耗尽,现在仅输出undefined表示值)。

也就是说,value有两种方法可以访问/传递它。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next

答案 1 :(得分:1)

混淆来自于yieldnext具有不同的语法,而实际上它们做同样的事情。生成器及其调用者是对称的(这就是为什么它们被称为“co” - 例程而不是“sub” - 例程)。这两种功能都可以被认为是通过通信通道连接的,并且可以完成工作或休眠等待通道中的传入消息。唯一的区别是发生器最初是睡着的(也就是说,它顶部有一个隐含的“listen”命令),而调用者最初是醒着的。

yieldnext执行相同的事情三件事:

  • 将其论点写入频道
  • 入睡并听取传入消息
  • 将传入的消息作为其值发出并唤醒(即继续使用它们下面的内容)

插图:

_ = console.log.bind(console)

function *gen() {
    _('gen: good morning')

    _('gen: sending hi')
    _('gen: zzz')
    p = yield 'hi'
    _('gen: awake! got', p)

    _('gen: now sending fine')
    _('gen: zzz')
    p = yield 'fine'
    _('gen: awake! got', p) // ***
}

function main() {

    var g = gen()

    _('main: sending knock knock')
    _('main: zzz')
    r = g.next('knock knock')
    _('main: awake! got', r)

    _('main: sending how r u')
    _('main: zzz')
    r = g.next('how r u')
    _('main: awake! got', r)
}

main()

请注意,由于写入在读取之前,因此发送到生成器的第一条消息将丢失。它只用于唤醒发电机。另请注意我们如何将生成器置于休眠状态,因此未到达***行。

答案 2 :(得分:0)

This makes it quite clear:

  

[rv] = yield [表达];

expression 定义通过迭代器协议从生成器函数返回的值。如果省略,则返回undefined。

rv 返回传递给生成器next()方法的可选值,以恢复执行。

基本上,您打印出已发送的参数以继续执行。