【问题标题】:Why is yield statement of a javascript generator function returning parameters of .next()?为什么 javascript 生成器函数的 yield 语句返回 .next() 的参数?
【发布时间】:2018-01-23 22:26:43
【问题描述】:

我偶然发现了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 时,它们实际上并没有作为生成器的输出而产生。我必须说我觉得这很混乱。

【问题讨论】:

  • ...因为这就是应该发生的事情?为什么这让你感到困惑?
  • 这就是 yield 表达式的计算结果。
  • @user2357112 它让我感到困惑,因为我没有看到上面代码中要引用的参数。阅读了答案中的链接后,现在一切都说得通了,但是当我第一次看到它时,我并不理解。作为旁注,您还可以执行 function* x() {yield yield yield;} 之类的操作

标签: javascript yield


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    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()

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

    【讨论】:

      【解决方案3】:

      This makes it quite clear:

      [rv] = 产量[表达式];

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

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

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

      【讨论】:

        猜你喜欢
        • 2020-04-07
        • 2016-03-19
        • 1970-01-01
        • 2012-08-17
        • 2019-01-08
        • 2014-01-25
        • 2015-06-07
        相关资源
        最近更新 更多