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

Why is yield statement of a javascript generator function returning parameters of .next()?

我偶然发现了 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 的参数 returns 参数传递给生成器的 .next() 方法.发生这种情况是因为空 yield 必须 return .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 语句将这些值 returning 到 console.log,但它们实际上并没有作为生成器的输出产生。我必须说我觉得它很混乱。

This makes it quite clear:

[rv] = yield [expression];

expression 通过迭代器协议将生成器函数的值定义为 return。如果省略,则 undefined 被 returned 代替。

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

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

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

next() 方法本身 returns 一个对象,具有属性 value 和一个布尔值 done 表示生成器函数是否完成(即耗尽可用输出,现在将只输出 undefined 作为一个值)。

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

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

混淆来自于 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()

请注意,由于写入先于读取,因此发送给生成器的第一条消息丢失了。它仅用于唤醒生成器。还要注意我们是如何让生成器处于休眠状态的,所以 *** 行没有到达。