作者:Alan Storm翻译:疯狂的技术宅
原文:https://alanstorm.com/javascr...
未经允许严禁转载
什么是生成器?
生成器是在函数内部运行的一些代码
- 返回值后,它会自行暂停,并且——
- 调用程序可以要求取消暂停并返回另一个值
这种“返回”不是传统的从函数 return
。所以它被赋予了一个特殊的名称——yield
。
生成器语法因语言而异。 Javascript 的生成器语法类似于 PHP,但是区别也很大,如果你希望它们的作用相同,那么最终你会感到非常困惑。
在 javascript 中,如果想要使用生成器,则需要:
- 定义特殊的生成器函数
- 调用该函数创建一个生成器对象
- 在循环中使用该生成器对象,或直接调用其
next
方法
我们以下面这个简单的程序做为起点,并执行以下每个步骤:
// File: sample-program.js
function *createGenerator() {
for(let i=0;i<20;i++) {
yield i
}
}
const generator = createGenerator()
console.log(generator.next())
console.log(generator.next())
如果运行这段代码,则会得到以下输出:
$ node sample-program.js
{ value: 0, done: false }
{ value: 1, done: false }
下面我来解释该程序是如何工作的。
生成器函数
首先,代码中存在生成器函数的定义:
function* createGenerator() {
for(let i=0;i<20;i++) {
yield i
}
}
function
后面的 *
告诉 javascript 这是一个生成器函数。以下写法都是生成器函数的有效定义。
function*createGenerator
function* createGenerator
function *createGenerator
*
并不是函数名的一部分。而是 function*
符号定义了生成器。
调用生成器函数
定义了生成器函数后,我们将其命名为其他名称的函数。
// 注意:当调用时,没有 *。 * 不是函数名称的一部分
// `function *` 是用于定义生成器函数的符号
const generator = createGenerator()
但是要记住:createGenerator
函数没有返回值。这是因为生成器函数没有传统的返回值。相反,当你直接调用生成器函数时,它总是返回实例化的 Generator
对象。
这个生成器对象具有一个 next
方法。调用 next
将在生成器函数内部运行代码。
function* createGenerator() {
for(let i=0;i<20;i++) {
yield i
}
}
这很重要,足以再次调用它。直接调用生成器函数不会在生成器函数中运行任何代码。而是创建一个生成器对象。它在生成器对象上调用 next
,从而调用生成器函数中的代码。
首次在生成器对象上调用 next
时,内部代码将会一直运行,直到出现 yield
语句。一旦执行到 yield
,javascript 将会暂停该代码的执行,而 next
将返回(即给你,或yield
)一个对象,该对象包含 yield
行中的值。
当你第二次(或第三次、第四次甚至更多次)再调用 next
时,代码将会取消暂停并继续运行(在上次调用时中断的地方)。变量(例如本例中的 i
)将会保持它的值。当代码到达另一个 yield
语句时,该函数会再次暂停,并返回一个包含 yield 值的对象。
这就是为什么我们要调用两次 next
console.log(generator.next())
console.log(generator.next())
会得到以下输出:
{ value: 0, done: false }
{ value: 1, done: false }
生成器函数中的代码执行完毕后,将来对 next
的任何调用都会返回一个对象,该对象的值为 undefined 且done
设置为 true
。
{ value: undefined, done: true }
生成器和循环
虽然可以在生成器对象上手动调用 next
,但我们主要是要在循环中使用。看一下这个稍作修改的程序。
// File: sample-program.js
@highlightsyntax@jscript
function *createGenerator() {
for(let i=0;i<5;i++) {
yield i
}
}
const generator = createGenerator()
for(const value of generator) {
console.log(value)
}
当在 for...of
循环中使用生成器对象时,每次循环都会在生成器对象上调用 next
,并用产生的值填充变量(上面的 value
)。运行该程序将会输出以下内容:
$ node sample-program.js
0
1
2
3
4
在下一篇文章中,我们将更深入地探讨 for ... of
循环,并探索怎样为 javascript 提供一种内置方法来循环 javascript 中的任何对象。
本文首发微信公众号:前端先锋
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章
欢迎继续阅读本专栏其它高赞文章:
- 深入理解Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13个帮你提高开发效率的现代CSS框架
- 快速上手BootstrapVue
- JavaScript引擎是如何工作的?从调用栈到Promise你需要知道的一切
- WebSocket实战:在 Node 和 React 之间进行实时通信
- 关于 Git 的 20 个面试题
- 深入解析 Node.js 的 console.log
- Node.js 究竟是什么?
- 30分钟用Node.js构建一个API服务器
- Javascript的对象拷贝
- 程序员30岁前月薪达不到30K,该何去何从
- 14个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩展插件
- Node.js 多线程完全指南
- 把HTML转成PDF的4个方案及实现
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。