Javascript生成器(Generator)的介绍与使用


Posted in Javascript onJanuary 31, 2021

什么是生成器?

生成器是在函数内部运行的一些代码

  • 返回值后,它会自行暂停,并且——
  • 调用程序可以要求取消暂停并返回另一个值

这种“返回”不是传统的从函数 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 中的任何对象。

总结

到此这篇关于Javascript生成器(Generator)的文章就介绍到这了,更多相关Javascript生成器(Generator)内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js跨域和ajax 跨域问题的实现思路
Sep 05 Javascript
javascript 类定义的4种方法
Sep 12 Javascript
js自定义事件代码说明
Jan 31 Javascript
AJAX分页的代码(后台asp.net)
Feb 14 Javascript
jQuery内容过滤选择器用法分析
Feb 10 Javascript
JavaScript检查数字是否为整数或浮点数的方法
Jun 09 Javascript
jsonp跨域请求数据实现手机号码查询实例分析
Dec 12 Javascript
数组Array的一些方法(总结)
Feb 17 Javascript
JS实现图片转换成base64的各种应用场景实例分析
Jun 22 Javascript
vue实现微信分享功能
Nov 28 Javascript
在小程序中推送模板消息的实现方法
Jul 22 Javascript
详解elementUI中input框无法输入的问题
Apr 27 Javascript
Node.js中的异步生成器与异步迭代详解
Jan 31 #Javascript
Vite和Vue CLI的优劣
Jan 30 #Vue.js
如何使用RoughViz可视化Vue.js中的草绘图表
Jan 30 #Vue.js
Element-ui 自带的两种远程搜索(模糊查询)用法讲解
Jan 29 #Javascript
小程序实现列表倒计时功能
Jan 29 #Javascript
JS相册图片抖动放大展示效果的示例代码
Jan 29 #Javascript
vue监听键盘事件的相关总结
Jan 29 #Vue.js
You might like
php miniBB中文乱码问题解决方法
2008/11/25 PHP
PHP字符串处理的10个简单方法
2010/06/30 PHP
PHP5中Cookie与 Session使用详解
2013/04/30 PHP
解决php-fpm.service not found问题的办法
2017/06/06 PHP
PHP如何根据文件头检测文件类型实例代码
2018/10/14 PHP
JS查看对象功能代码
2008/04/25 Javascript
js parentElement和offsetParent之间的区别
2010/03/23 Javascript
事件模型在各浏览器中存在差异
2010/10/20 Javascript
JS高级运动实例分析
2016/12/20 Javascript
js多个物体运动功能实例分析
2016/12/20 Javascript
vue脚手架vue-cli的学习使用教程
2017/06/06 Javascript
javascript 取小数点后几位几种方法总结
2017/08/02 Javascript
node跨域转发 express+http-proxy-middleware的使用
2018/05/31 Javascript
JS闭包经典实例详解
2018/12/20 Javascript
基于JS实现前端压缩上传图片的实例代码
2019/05/14 Javascript
微信小程序页面间跳转传参方式总结
2019/06/13 Javascript
微信小程序实现传递多个参数与事件处理
2019/08/12 Javascript
Vue实现简易计算器
2020/02/25 Javascript
AutoJs实现刷宝短视频的思路详解
2020/05/22 Javascript
vue-cli3 热更新配置操作
2020/09/18 Javascript
[26:40]DOTA2上海特级锦标赛A组资格赛#1 Secret VS MVP.Phx第一局
2016/02/25 DOTA
Python中apply函数的用法实例教程
2014/07/31 Python
Python中字典(dict)合并的四种方法总结
2017/08/10 Python
jupyter notebook实现显示行号
2020/04/13 Python
Keras:Unet网络实现多类语义分割方式
2020/06/11 Python
Vs Code中8个好用的python 扩展插件
2020/10/12 Python
Python绘制词云图之可视化神器pyecharts的方法
2021/02/23 Python
css3实例教程 一款纯css3实现的环形导航菜单
2014/10/20 HTML / CSS
html5基础教程常用技巧整理
2013/08/20 HTML / CSS
我的珠宝盒:Ma boîte à bijoux
2019/08/27 全球购物
指针和引用有什么区别
2013/01/13 面试题
项目转让协议书
2014/10/27 职场文书
离婚协议书怎么写
2015/01/26 职场文书
房地产销售主管岗位职责
2015/02/13 职场文书
公司客户答谢酒会祝酒词
2015/08/11 职场文书
sqlserver连接错误之SQL评估期已过的问题解决
2022/03/23 SQL Server