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 相关文章推荐
javascript preload&amp;lazy load
May 13 Javascript
javascript获取元素CSS样式代码示例
Nov 28 Javascript
TypeScript具有的几个不同特质
Apr 07 Javascript
JavaScript添加随滚动条滚动窗体的方法
Feb 23 Javascript
利用Three.js如何实现阴影效果实例代码
Sep 26 Javascript
JQuery 又谈ajax局部刷新
Nov 27 jQuery
vue+Element-ui实现分页效果实例代码详解
Dec 10 Javascript
vue中datepicker的使用教程实例代码详解
Jul 08 Javascript
javascript实现抢购倒计时程序
Aug 26 Javascript
node.js域名解析实现方法详解
Nov 05 Javascript
vue接口请求加密实例
Aug 11 Javascript
Vue 按照创建时间和当前时间显示操作(刚刚,几小时前,几天前)
Sep 10 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教程 变量定义
2009/10/23 PHP
一些PHP Coding Tips(php小技巧)[2011/04/02最后更新]
2011/05/02 PHP
php.ini中date.timezone设置详解
2016/11/20 PHP
Laravel 实现在Blade模版中使用全局变量代替路径的例子
2019/10/22 PHP
学习ExtJS TextField常用方法
2009/10/07 Javascript
js 实现css风格选择器(压缩后2KB)
2012/01/12 Javascript
使用Jquery Aajx访问WCF服务(GET、POST、PUT、DELETE)
2012/03/16 Javascript
Eval and new funciton not the same thing
2012/12/27 Javascript
原生js实现可爱糖果数字时间特效
2016/12/30 Javascript
js获取元素下的第一级子元素的方法(推荐)
2017/03/05 Javascript
基于vue2框架的机器人自动回复mini-project实例代码
2017/06/13 Javascript
AngularJS实用基础知识_入门必备篇(推荐)
2017/07/10 Javascript
vue实现带复选框的树形菜单
2019/05/27 Javascript
Javascript如何实现双指控制图片功能
2020/02/25 Javascript
vue3为什么要用proxy替代defineProperty
2020/10/19 Javascript
[43:32]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS NewBee第一场
2014/05/26 DOTA
Python中关于字符串对象的一些基础知识
2015/04/08 Python
Python实现包含min函数的栈
2016/04/29 Python
Python实现读取文件最后n行的方法
2017/02/23 Python
python实现kmp算法的实例代码
2019/04/03 Python
Python获取一个用户名的组ID过程解析
2019/09/03 Python
Python小程序之在图片上加入数字的代码
2019/11/26 Python
Django认证系统user对象实现过程解析
2020/03/02 Python
美国的Eastbay旗下的运动款子品牌:Final-Score
2018/01/01 全球购物
Bath & Body Works阿联酋:在线购买沐浴和身体用品
2021/02/27 全球购物
Linux如何压缩可执行文件
2013/10/21 面试题
新闻记者实习自我鉴定
2013/09/19 职场文书
三下乡活动方案
2014/01/31 职场文书
小学生母亲节演讲稿
2014/05/07 职场文书
2015年度班主任自我评价
2015/03/11 职场文书
病危通知书样本
2015/04/17 职场文书
老乡聚会通知
2015/04/23 职场文书
2015年班组建设工作总结
2015/05/13 职场文书
百万英镑观后感
2015/06/09 职场文书
tensorflow学习笔记之tfrecord文件的生成与读取
2021/03/31 Python
go设置多个GOPATH的方式
2021/05/05 Golang