说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

【探秘ES6】系列专栏:生成器

HTML文档下载 WORD文档下载 PDF文档下载
新一代JavaScript标准,ES6即将发布。【探秘ES6】系列专栏将一一剖析ES6的诸多新特性,让Web开发者对此有清晰全面的了解。本文为系列的第三篇,带你了解ES6的生成器。

ES6作为新一代JavaScript标准,即将与广大前端开发者见面。为了让大家对ES6的诸多新特性有更深入的了解,Mozilla Web开发者博客推出了《ES6 In Depth》系列文章。CSDN已获授权,将持续对该系列进行翻译,供大家学习借鉴。本文为该系列的第三篇。

ES6生成器介绍

什么是生成器呢?

请先看看以下代码。

function* quips(name) {  yield "hello " + name + "!";  yield "i hope you are enjoying the blog posts";  if (name.startsWith("X")) {    yield "it's cool how your name starts with X, " + name;  }  yield "see you later!";}

这是一段有关汤姆猫(talking cat)的代码。它看上去像是一个函数,是吗?在ES6中,它的名字是生成器函数,其与普通函数有很多相似的地方。但有两点不同:

  • 生成器函数以function*开头;
  • 在生成器函数中,yield是一个关键字,如同return。yield可以多次使用,作用是中断生成器,

    而在需要的时候可以恢复生成器的执行

所以生成器函数最大的特点是可以中断自己,但普通函数不可以。

生成器的作用

当使用quips()生成器函数时会出现什么情况呢?

> var iter = quips("jorendorff");  [object Generator]> iter.next()  { value: "hello jorendorff!", done: false }> iter.next()  { value: "i hope you are enjoying the blog posts", done: false }> iter.next()  { value: "see you later!", done: false }> iter.next()  { value: undefined, done: true }

对于普通quips(),它会马上执行直到出现返回或异常抛出等情况。在生成器函数中,调用方式是类似的:quips("jorendorff"),但是它不会马上执行。取而代之的是,它会返回一个已暂停的生成器对象(如上述代码的iter)。你可以把生成器对象看成是一个被暂停的函数调用。要特别说明的是生成器对象在生成器函数开始时被冻结,即第一行代码执行之前。

每当调用生成器对象的.next()方法时,函数恢复运行直至遇到下一个yield表达式,其作用是用于迭代。因此iter.next()的目的是为了返回不同的字符串。在最后的iter.next()中,使用done:true表示结束。到达函数末端意味着返回的结果是undefined,所以代码片段中使用value: undefined结尾。

从技术角度来看,每当生成器执行yield操作时,它的堆栈帧包括本地变量、参数、临时值等都会从堆中被移出。但是生成器对象会保留(拷贝)对该帧的引用,所以.next()可以重新激活它然后继续执行。这里特别要说明的是,生成器不是线程。当一个生成器执行时,它与其调用者都处于同一个线程,是按次序执行而不是并行运行。

可见生成器的作用是暂停本身的运行,然后恢复并继续执行,那么这究竟有何用处呢?

生成器就是迭代器

ES6迭代器不是内建的,可尝试通过使用[Symbol.iterator]()和.next()来进行创建。但是这种类似接口的做法不是最简便的方法。请看下面一个range迭代器例子,它的作用类似于C的for(;;)循环。

// This should "ding" three timesfor (var value of range(0, 3)) {  alert("Ding! at floor #" + value);}

具体的实现代码:

class RangeIterator {  constructor(start, stop) {    this.value = start;    this.stop = stop;  }  [Symbol.iterator]() { return this; }  next() {    var value = this.value;    if (value < this.stop) {      this.value++;      return {done: false, value: value};    } else {      return {done: true, value: undefined};    }  }}// Return a new iterator that counts up from 'start' to 'stop'.function range(start, stop) {  return new RangeIterator(start, stop);}

要查看运行情况请点击这里。

可见迭代器的生成并不是件简单的事情。那么如果采用生成器来实现,应该如何编写呢?

function* range(start, stop) {  for (var i = start; i < stop; i++)    yield i;}

要查看运行情况请点击这里。

对比是很明显的,上述代码仅需4行代码就完成了相同的功能,因为生成器就是迭代器。所有生成器都内建了对.next()和[Symbol.iterator]()的支持,你只需要负责循环的实现就可以了。

除此以外,作为迭代器使用的生成器还可以实现哪些功能呢?

  • 使任何对象可迭代。方法是编写一个生成器函数,然后对每个值进行迭代。然后使用对象的[Symbol.iterator]方法与生成器函数进行绑定。
  • 简化数组功能。如果要实现以数组形式返回函数结果,可以这样写:

// Divide the one-dimensional array 'icons'// into arrays of length 'rowLength'.function splitIntoRows(icons, rowLength) {  var rows = [];  for (var i = 0; i < icons.length; i += rowLength) {    rows.push(icons.slice(i, i + rowLength));  }  return rows;}

如果使用生成器编写,可以把代码简化为:

function* splitIntoRows(icons, rowLength) {  for (var i = 0; i < icons.length; i += rowLength) {    yield icons.slice(i, i + rowLength);  }}

后者与前者的区别是不是一次就计算所有结果并返回一个数组,而是先返回一个迭代器,然后按次序按需进行计算。

  • 返回特殊长度数组。数组是有长度限制的,但是透过生成器迭代特性,可以产生无限的序列。
  • 重构复合循环。当编写一个复杂的循环时,可以提出产生数据的部分,把它改写为一个独立的生成器函数。例如(var data of myNewGenerator(args))。
  • 进行迭代运算的配套工具。ES6并没有提供有关筛选、映射、迭代数据集操作的扩展库。但是借助生成器,我们可以围绕它来简单地创建相关工具。

例如,要在DOM节点上实现与Array.prototype.filter类似的功能,可以这样编写:

function* filter(test, iterable) {  for (var item of iterable) {    if (test(item))      yield item;  }}

可见,生成器真的妙不可言。借助生成器可以方便地实现定制的迭代操作,而迭代是ES6中贯穿始终的新的数据和循环标准。

生成器和异步代码

请看一段代码:

}).on('close', function () {  done(undefined, undefined);}).on('error', function (error) {  done(error);});

异步APIs提供的是错误处理而非异常处理,不同APIs有不同的处理方法。而大多数错误定义是默认的,所以进行异步编程时需要花一定时间去了解。生成器则提供了新的处理方式。

Q.async()是一个实验性的类似于同步代码的异步代码生成方法,请看代码:

// Synchronous code to make some noise.function makeNoise() {  shake();  rattle();  roll();}// Asynchronous code to make some noise.// Returns a Promise object that becomes resolved// when we're done making noise.function makeNoise_async() {  return Q.async(function* () {    yield shake_async();    yield rattle_async();    yield roll_async();  });}

两者的主要区别是异步代码必须使用yield关键字来执行异步函数。因此生成器为新的异步编程模型带来了新的思路,更符合人的思维习惯。

写在最后

限于篇幅,生成器还有两个方法留待后续讲解,.throw()和.return()。多看官方文档多动手练习,你会发现ES6更多精彩。(译者:伍昆 责编:陈秋歌)

原文链接:ES6 In Depth: Generators

本译文遵循Creative Commons Attribution Share-Alike License v3.0 

相关阅读:

【探秘ES6】系列专栏:ES6简介

【探秘ES6】系列专栏:迭代器和for-of循环

欢迎加入CSDN前端交流群:218126086,进行前端技术交流。  

人人网推出开放平台2.0 多项重大改进吸引开发者回流 红帽高管:将Linux价值理念和做法延伸到OpenStack Fundation 5发布:号称最快版本,响应式用户体验更完善 程序员远程工作必会编程语言JavaScript 苹果确认收购3D传感技术公司PrimeSense 从电影《饥饿游戏》里学到的IT知识 细数IE11的七大变化 2013中国大数据技术大会,你不可错过的10个理由 Unity 2D全球发布,开发者梦想照进现实 Kraken:改变PayPal开发文化的Node.js框架 微软高管:我们将不会再有三个Windows平台 中兴明年推智能手表 暂只能与自家手机搭配使用 移动开发必备!15款jQuery Mobile插件 Chrome新变化:在地址栏里增加搜索按钮 电信行业大数据实践走进大数据大赛:电信网络寻呼黑洞分析 京东云开发者沙龙(北京站):“千人千面”的机遇 小工具、大能量——2013移动开发工具调查报告 人人网重新布局移动社交战略 专注学生群体发布新版移动客户端 谷歌把“OK,Google”带到Chrome 让PC也能便捷语音搜索 美国女性工程师远没有你想象的多 技与艺:对话《雨血》系列制作人梁其伟先生 2014年平板电脑或将占PC市场的“半壁江山” 【开源推荐】Nutz:Java项目中SSH框架的最佳替代品 你的数据库准备好过冬了吗 开源将成为SDN最大的风险! “大姨吗”CEO柴可:女性健康白皮书的发布与“大姨吗”的未来 看中国大学生的移动创意激情 第六届英特尔杯软件创新大赛侧记 在哪里工作更好?Facebook大胜Google WDC超链接图:涵盖35亿网页、1280亿超链接 英特尔:机器已扛不住亚洲的空气污染 IE11中全新增强的F12开发人员工具 AUTOCAD图形打印驱动程序设计 AUTOCAD图形打印驱动程序设计 情帮忙(50分) 一个水晶报表的问题 有人真正使用过XML开发程序么? 我想买书 pb7.0哪里可以下载? AUTOCAD图形打印驱动程序设计 贺猪猪成星,散分给水友,天下皆欢颜!!! WinRAR的压缩密码怎么取消啊?快,快,急需!!! 没有权限打开names.nsf的问题? 复选框的问题,在线等待!!! 没有权限打开names.nsf的问题? IE浏览器显示的字体不是默认的,变成了空心字体。如何改成系统默认的字体?(win98+IE5.0) 寻找高手 关于协议的问题 求助!能把一个字段内容分解的函数? Servlet问题?(急等,立结) oleconnection 支不支持sybase的连接,不通过odbc如何连接Sybase高手请进!急啊!!! 关于return的问题 为何内存消耗在不断增长? 浏览器类型 求文件长度? 用DELPHI 开发过ORACLE数据库的高手帮忙,我现在遇到个问题, BCB消息机制问题, 关于MFC 请教:jar问题 零为什么不能做为除数。 菜单资源ID得问题 请问高手,实验室局域网内部下载速度很慢,会是什么原因造成的? 如何利用Datareport做出好看一点的报表? Grid的列怎么来调整? GDI+类使用new操作符问题 有人在吗? 请看看这一样个SQL语句 页面上有两个相连的表格时,中间的边框变得很粗,能否做到和一个表格的效果? 帮我写一个简单的和SERVER2000查询的例子50分相送!! 怎样将别人给我的数据库文件导到本地? 近日较忙,散分200 请问将脚本写在页面和写在J文件里有什么不同?我写在页面上一切正常,可是把脚本防在一个JS文件就报错 ===好几天,ADO 连接oracle数据库的问题.还搞定。大伙给看看 DBLookupComboBox的疑问 我是福建省福州的.程序员在哪儿报名呀?? 如何让录入页面的信息能自动保存~! 编写函数 有谁知道华工的计算机应用的复试考那几门?另外请问关于其他不公布复试科目的学校可以通过电话询问复试科目吗? 想不通,请教?(802.1x) 一个有关浏览器的问题,高手必进! 那位兄弟推荐一款文件夹加密的软件! 发布一套完整的网站系统,up就给分 怎么样能够把文件上传到服务器的任意目录下?? java同mysql连接不上: Server configuration denies access to data source 什么是锡铋合金?我知道肯定不是伍德合金, 提供毒品原材料 是什么归责原则 麦克斯韦的电磁理论,不是说非均匀变化的电场产生变化的磁场,为什么...麦克斯韦的电磁理论,不是说非均匀变化的电场产生变化的磁场,为什么一直导线通以直流也会产生磁场呢?不是变化的 ,你好!我长期从事熔炼锡和铋两种金属的工作 ( 锡.铋合金模具)请问在熔炼锡.铋两种元素时所产生的气体是否对人体人害. 是否是接毒工种.谢谢! 过氧化钠与溴离子,碘离子,亚铁离子,亚硫酸根可会发生氧化还原反应?过氧化氢呢? 当年……,如今…… 怎么造句 东莞买锡铋合金去哪里啊?那里的质量好呢? 溴单质能氧化过氧化钠吗?最好能提供一下常见氧化剂的氧化性顺序 用三个有时造句, 为什么氧不是构成细胞的最基本元素 硝酸是否可以氧化溴离子 当年……如今……造句 在这英雄的土地上,我要怎么样地高声歌唱!扩写句子 组成细胞的元素中最多的是氧还是氢? 硝酸能不能将溴离子氧化?如题 原线圈输入正弦型交流电压 经过理想变压器变压后得到的电压是正弦型还是余弦型? 趁对方没有预料到就采取行动用什么词语来形容 本草纲目共多少卷…?多少药材?公认的毒药多少种 方向如图所示的匀强电场(场强为E)和匀强磁场(磁感应强度为B)共存的场区······方向如图所示的匀强电场(场强为E)和匀强磁场(磁感应强度为B)共存的场区,一电子沿垂直电场线 请问用什么词可以形容对方对自己的重要性?要非常非常深的词才行 .因为我们的关系非常铁!我觉得命脉不错,但是很多人用.希望你们可以多多提议 氧化那次如何转化为过氧化钠,方程式是什么? 英国物理学家、数学家麦克斯韦的智商是多少? 一个小球以V的速度方向与水平地面撞击垂直于竖直的墙后反弹为什么还是V? 鱼跃制氧机到底怎么样 准备买制氧机准备买制氧机了,听人讲到鱼跃制氧机, HCLO强氧化性反应方程式为什么它自身分解就可以体现出强氧化性? 小明一家10点10分离家赶11点整的火车去某地旅游,他们家赶离火车站 好像是2NA2O2+2NA===4NA2O但是我不知道反应条件 用…………时,它会…………造句 用…………时,它会…………造句 记住是这个它 谁能告诉我李大钊有哪些故事?不要太罗嗦的就好. 将70克Na2O2和Na2o的混和物跟98克水充分反应后,所得氢氧化钠溶液的质量分数为百分之五十,求混和物中的过氧化钠与氧化纳的质量 用“之所以.不仅仅.而且”造句《求速度》 谁有李大钊的故事, 过氧化钠中纳几价? 这个电脑电源功率是多少? 为什么叫光纤?不就是玻璃吗?光芯和包层都是以 较高纯度的 sio2 加以少量掺杂剂构成的 ,包层就比纤芯折射率低点,那么 为什么 要叫光纤呢 难道就是 因为 芯很小 就叫光纤? 怎样理解凯恩斯的“有效需求”概念?假如某一年的总供给大于总需求,同时存在着失业国民收入和就业将会产生什么变化?凯恩斯认为应采取何种对策? 在相同条件下氧气的溶解度大于氢气的溶解度,实验中测得比值会比理论值偏___理由: 关于光纤线玻璃芯光传导的问题?我将光纤线中玻璃芯(玻璃纤维)取出,放入透明塑料管内,塑料管内壁敷上玻璃芯,一层塑料包裹的玻璃纤维能否传导光? 关于李大钊的事例(2个)有的话再发几条名言 甲管与乙管中产生的气体体积比约为2:1.由于在相同条件下氧气在水中的溶解性要大于氢气,实验中测得的结果 工业十水合四硼酸二钠怎么转换成硼含量 在误解的情况下用什么词表示 在相同条件下氧气的溶解度大于氢气的溶解度,实验中测得比值会比理论值偏大吗是大还是小? 无氧铜化学成分? 误解太深 总是拿自己的所作所为去想别人 用哪个词来表达 优美凄凉的句子 氧气遇到什么化学成分会起火? 电解中氢氧根放电发生氧化反应,为何不会生成氢气? 氧化钙与二氧化碳反应生成碳酸钙要打沉淀符号吗 电池正常的充电放电截止电压是怎么算的?有镍镉,镍氢,电池.当然每一个电池的电压都不样,为我解答这问题小弟我感激不尽! 这个电解得反应咋写啊 为啥是硝酸根放电不是氢氧根放电?因为溶液是酸性得? 应用麦克斯韦的电磁理论判断如图所示的表示电场产生磁场(或磁场产生电场)的关系图应用麦克斯韦的电磁理论判断如图所示的表示电场产生磁场(或磁场产生电场)的关系图象中(每个选 李大钊的故事100字左右 过氧化氯氧化氯离子在酸性条件还是在碱性条件下,过氧化氢可以氧化 氯离子变为氯气 PH值为多少比较好 有没有一些凄凉优美的句子 锡-铋合金相图的绘制:共晶点铋的百分含量是多少?共晶温度是多少? 那些物质可以氧化氯离子? 应用麦克斯韦的电磁理论判断如图所示的表示电场产生磁场(或磁场产生电场)的关系图象中(每个选项中的上图是表示变化的场,下图是表示变化的场产生的另外的场),正确的是( ). 锡铋合金现在价格大概在多少呢. 这个叫什么?属于毒品吗?我很喜欢去酒吧玩,但是从来不磕药的.记得有一次喝多了,朋友拿了一瓶饮料给我,整个瓶子都是蓝色的,喝起来甜甜的,感觉还不错,上面好像写着蓝精灵三个字(当时喝 麦克斯韦方程中关于变化的电场产生磁场及变化的磁场产生电场是推论出来的么? 中方支持安理会继续改进工作方法杨洁篪会见伊朗伊斯兰议会议长拉里贾尼伦敦股市股指29日上涨欧洲强风暴抵达俄罗斯西北地区环保税引发民众暴力抗争 法国政府宣布农业主产区生产积极性不高 农业干部“黎巴嫩拒绝叙利亚化学武器进入其领土伦敦股市《金融时报》100种股票平均王正伟访问巴基斯坦德国法兰克福股市DAX指数29日上涨厄瓜多尔欲向斯诺登提供政治避难粮食主产区财政紧张陷怪圈:产粮越多经英国将发行伊斯兰债券 吸引中东投资者美国1名店员遭劫匪枪击 胸前手机挡下英国将发行伊斯兰债券 吸引中东投资者“今日中国 中国电影周”于曼谷开幕法国巴黎CAC40股指29日上涨英国计划发行2亿英镑伊斯兰债券NBA新赛季大幕正式拉开 各路豪强谁NBA新赛季球星篇:科比状态成疑 魔联合国官方微博发布反战视频 吁挽救叙吴曦:我们有能力立足亚洲 佩兰是个有联合国通令嘉奖中国驻利维和警察防暴队新华国际时评:阿尔卑斯山上传递中国信联合国通令嘉奖中国驻利维和警察防暴队李克强会见世界卫生组织总干事陈冯富珍新疆福海县乌伦古湖冬捕节拉动淡季旅游山东威海一居民楼发生爆炸欧洲央行宣布每月600亿欧元大规模国中国商务部:美对华第二起光伏双反案损欧洲央行宣布每月600亿欧元大规模国中国商务部:美对华第二起光伏双反案损欧洲央行宣布每月600亿欧元大规模国吉林省探索实行“三证合一”登记制度张焕秋当选吉林市市长贵州去年查处违反八项规定案件5043云南省纪委2014年立案查处厅级干部业主贴大字报指他人私占租金 内容不实朝鲜再次提议改善朝韩关系巴音朝鲁蒋超良会见徐和谊省政协召开主席会议人物:“二蛋”孙可
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘