我正在从 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的值?
最佳答案
在使用协程时,重要的是要了解,尽管 yield
和 next
是不同的关键字,但它们所做的本质上是相同的。想象两个协程通过双向通信管道连接。两者
Y = yield X
和
Y = next(X)
执行同一组操作:
- 将X写入管道
- 等待答案
- 一旦有了答案,就从管道中读取它并将其分配给 Y
- 继续执行
最初,主程序处于事件状态,生成器(在您的示例中为 gen2
)正在等待监听管道。现在,当您调用 next
时,主程序会向管道写入一个虚拟值 (null
),从而唤醒生成器。生成器执行yield 100
,将100
写入管道并等待。 main 唤醒,从管道读取 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
的结果时,右和左(或“生成”和“使用”)部分。当你做的时候
var a = 5
这是立即执行的,而
var a = yield 5
涉及 =
和 yield
之间的停顿。这需要一些脑力训练,与 async
工作流非常相似,但随着时间的推移您会习惯的。
关于Javascript 函数生成器参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49321216/