生成器 Generator
2023 javascript生成器 Generator 使得函数可以通过 yield 暂停,并且暂停还可以通信,通信结束后可以继续执行。其上下文会被保存。
生成器 Generator
function* 声明定义了一个生成器函数,返回一个 Generator 对象。
function* name(param0) {
statements;
}
fucntion* name(param0, param1, /*...,*/ paramN) {
statements;
}
调用一个生成器函数不会被立即执行,而是返回一个可迭代的生成器对象。当该迭代器的 next()
方法被调用,该生成器才会被执行,并返回第一个 yield
的表达式。该迭代器返回一个包含了一个 value
属性的值和一个 done
的布尔值的对象。
fucntion* generator() {
yield 10;
}
const it = generator();
const res = it.next(); // res = { value: 10, done: true }
return 语句在生成器里被执行的时候,将使该生成器结束(done
变成 true
)。
yield
yield
操作符用来暂停和恢复生成器函数。
[rv] = yield[expression];
yield 关键字暂停生成器函数的执行,并且紧随在 yield 关键字后的表达式会被返回。可以当作生成器独有的 return 关键字。
一旦生成器函数在 yield 表达式暂停,生成器将会被暂停直到下一次生成器的 next 方法调用。
消息传递
除了能够接受参数并提供返回值之外,生成器甚至提供了更强大的内建消息输入输出能力,通过 yield 和 next() 实现。
function* foo(x) {
const y = x * (yield);
return y;
}
const it = foo(6);
// 启动 foo()
it.next();
const res = it.next(7); // res = { value: 42, done: true }
在执行语句 const y = x * (yield),会遇到 yield 表达式,就会暂停函数。并在本质上要求调用代码为 yield 表示式提供一个结果值。调用 it.next(7),将值 7 传回作为被暂停的 yield 表达式的结果。 一步一步理解 Generator 函数的原理 在通过内建消息输入的时候,需要调用的 next() 调用要比 yield 多一个。因为第一个 next 总是启动一个生成器。
原理
Generator 函数是协程在 ES6 的实现,遇到 yield 命令会暂停,将执行权交出去,等执行权回来之后继续从暂停的地方开始执行。
协程(Coroutines)是一种比线程更加轻量级的存在,一个线程可以拥有多个协程。
总结下来:
- 一个线程存在多个线程
- Generator 函数是协程在 ES6 的实现
- yield 挂起协程,next 唤起协程
参考链接
- MDN: generator
- MDN: function*
- MDN: yield
- 《你不知道的 JavaScript》- 生成器
- 一步一步理解 Generator 函数的原理