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

【探秘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,进行前端技术交流。  

又摊上事儿了,Android的MasterKey再次出现bug 比特币挖矿必备工具 硬件性能大比拼 RDBMS vs. NoSQL:反派为什么会得以存活并发展壮大 帮助优化移动网站:谷歌发布新指南和PageSpeed Insights工具 增强Web可用性,你需要避免的七大设计错误 Python六大开源框架对比:Web2py略胜一筹 海外看中国:老外开发者间流传着的7件事儿 京东云峰:电商移动云平台背后的技术 初创公司DigitalOcean:55秒搭建一个云服务器 分布式系统事务原子性的非阻塞实现 IBM发布基于人脑特性设计的全新计算架构和编程语言 16款加速编码的HTML5在线工具 JFrog:开源项目的最大挑战是文档和许可 5个技巧打造完美用户体验,不到两年完成用户万到千万的增长 CDN未来的机遇和挑战 华为S12700全可编程交换机进一步挑战思科 OpenFient创始人:将平台创新进行到底 专访Ubisoft手游团队:“波斯王子”的时光机器 技术大牛Jiva DeVoe:App Store往事追忆录 移动周报:苹果iOS开发者中8位公认的“女神” Paul Graham:创业者如何说服投资人? 【CTO俱乐部深圳站】企业大数据建设案例分享 Gmail新设计影响邮件营销 Fcaebook间接获利 百度高德小米网易杭研讲师登场 SDCC 2013第二批议题发布(图) [开源推荐]JS-Git:一款纯JavaScript实现的Git项目 良心企业Lavabit、Slient Mail相继关闭,美国云安全已死? 一周观察:LXC真的是PaaS的未来吗? [企业开源系列]Google背后的开源力量 合作: “云”潮中淘金的金钥匙 Windows 8.1尚未发布 Build 9471版遭泄露网爆高清大图 Imangi创始人:我眼中的App Store 有会用SDL(Simple DirectMedia Layer)的么? 如何重新启动电脑啊 ooad 有人对xml文档及schema映射为数据库的记录和表作过研究吗? 窗体启动时,Load之后是什么事件 安装好了J2EESDK1。4后怎样运行JAVA程序? 有关DBGrid的问题 IBM的硬盘是不是很菜!惨啊!奉劝大家多多备份,不要买IBM的盘 合格的程序员应该具备哪些知识和技能? 在报表中如何显示出来----共n页/第几页 急寻广州深圳两地图书城管理软件公司 用jdk写出的application里的汉字很难看,有没有解决的办法? 面向对象分析与设计 那位有<<java大学教程>>的光盘,可不可以把光盘上的附录部分发给我!(100分) 关于win2000中的odbc的问题 vfw 软件工程师和程序员有什么不同? 一方有难,八方支援,我有疑难,你能否来? 唉。 发现有人还在吃糠。。。。痛心ing.............. 为什么我连不到mysql? 有什么比做ghost更好的硬盘数据备份方法? 请教:在dataGrid 中如何根据行值的不同,设置不同的颜色 一般菜的问题,不知道你遇到过没有,请大家过来看一下 分析与设计 3D場景鋸齒消除問題 一方有难,八方支援,我有疑难,你能否来? 发布新软件,请帮助测试 一个白痴问题!哪个函数可以去除字符串中的空格? 在两台服务器上的数据库间创建触发器的注意事项? 有一好的想法,但途中这个问题搞不定 各位高手,请问用API怎样获得本机的网卡的IP地址 面向对象ooad 有没有类似deltree功能的函数啊? weblogic初级问题 小问题, 如何把个DBIMAGE里的图片复制到剪贴板里去?? 如何正确更新ADO的记录 分全给出,各位大侠看一看为什么动态库中的窗体调不出来:。。。。 更佳编程之路(转贴) 菜鸟问什么是水晶报表? 我的第一次发问? 集思广益整理一下有关类型转换的函数!(出力的都有分!!!不够再加!!) 有高分!有高分!有高分!有高分! 大家都用什么工具来做J2ME开发?调查一下!!! 急!sql server中的数据备份我在用程序操作,应如何写那(在deplhi中) msdn的提问~~~ datagrid的滚动条上下滚动的事件是什么阿? OOAD提示 SOFT-ICE的使用! 在C++Builder中怎么将相对于1980年1月1日0分0秒的秒计数换算成日期? 链接服务器:OLE DB提供程序'MSDAORA'报错,连接失败 用VB创建了一个SQL表并填数,时间长了就没了,怎么回事(在线等) 全站仪水平度盘不动,转动望远镜水平读数为什么变化? (求过程)函数f(x)的图象如图所示,则它的最大值、最小值分别为:f(0),f(3/2)为什么? 3/5×6/5简算 全站仪引点时坐标读数是错的是什么问题?测站点和后视点都没有错.就是照准好了以后对中棱镜测点得出的坐标读数是错的.是不是全站仪坏了?有哪个见到这样的问题? 我做个很奇怪的梦不知道什么意思,希望谁能给我解答下~是这样的:梦里我住在一个四合院里,有一些模糊的人(这些人的脸很模糊看不清楚,而且我都不认识.但他们和我很熟悉)在和我一起 √6(√8+√3)-(√5+√3)(√5-√3)的简算过程以及答案 7x-x^2=10 x=? 一个男生给我看他的日记,还说这是我们之间的秘密,一天上自习他传纸条过来 他:给你看个东西,有兴趣没?我:嗯.什么?他:那你先答应不许笑我,而且替我保密.因为这里写的东西我从没让别人看 3.6+3.6*(3.6-3.6/3.6)/3.6如何简算 10-7x=x+2 有个同学给我发了一句奇怪的话,我看不懂,E6%96%87%E4%BB%B6%E8%90%BD%E5%AE%9E%E6%83%85%E5%86%B5&i=somanythings...他说让我自己想,5555555.好心的大哥大姐帮帮忙啊~ 、正方形ABCD 中,△BKC 是直角三角形,KB=2,KC=1. MN 平行于DC 交AD、BC 于M、N, PQ 平行于AD 交AB、DC正方形ABCD 中,△BKC 是直角三角形,KB=2,KC=1. MN 平行于DC 交AD、BC 于M、N,PQ 平行于AD 交AB、DC 于P、Q.那么 利用因式分解计算如何算?(1-1/2^2)×(1-1/3^2)×………………x(1-1/2013^2) 有谁知道铝粉在耐火材料中的作用请详细说明金属铝粉在耐火材料中是做什么用的,哪些耐火材料需要用铝粉? 如图,AD∥BC,AB∥DC,MN=PQ,试说明DE=BE的理由 怎么算因式分解 生产涂料,太阳能用铝粉时,不合格的铝粉可以用在哪些途径?耐火材料和烟花中可用吗?还有哪些途径可用?耐火砖和烟花用铝粉有哪些具体要求 参数标准 比如粒径,纯度或者其他? 在梯形ABCD中,AD平行BC,AB=DC=8,∠B=60°,BC=12,MN分别是AB DC的中点,连接MN .求 MN 帮我算一下.因式分解 函数y=3x+2的图像与y=1/x的图像交点的集合.请用描述法和列举法、写出过程谢谢. 发生在隋朝的历史事件(台湾) 铝粉的主要用途是什么? X²-3X-4=0用列举法怎么表示? 跪求隋朝发生的重大历史事件!是历史事件就给我!不要台湾的!加年代!589(或581)到618年的,还有每次发生任何一个事件都要写!每次的都写长点,好的给一堆分!再次说明一下:隋朝发生的历史事件, 色漆中铝粉的作用是什么? 9、10、11、12急! 猪笼草是一种食虫植物,为了验证猪笼草分泌液中有蛋白酶,详细分析下! 已知在10只产品中有2只次品,在其中取两次,每次任取一只,作不放回抽样求下列事件的概率:2只都是正品.一只是正品,一只是次品.第2次取出的是次品.是用排列还是组合啊. 铝粉用途 梯形ABCD中,AD∥BC,AD∥MQ,且分别交BD于N,AC于P,M在AB上,Q在CD上求证:MN=PQ, 【考试在线】有10件产品,其中有2件次品,每次抽取1件检验,抽检后不放回,共抽2次.求下列事件的概率问题一,两次抽到的都是正品问题二,第一次抽到正品,第二次抽到次品问题三,抽到的恰有一 铝粉主要有哪些?用途是什么 上海世博会的英文主题曲是什么这次上海有一首很好听的英文主题曲,是一名外国女歌手所唱的,不知道叫什么名字,希望知道的人能帮助我一下, 在10件产品中有2件次品,现从中无返回抽取3件,计算下列事件的概率:(1)恰有2件正品 (2)含有次品 牛的头数比羊的只数多25%,羊的只数比牛的头数少百分之几?要用方程法,要有算式、过程、结果. 1.2.3.4.5.6. 雪的周记500字 两个乘积的3/1是-6,其中一个数是-4的绝对值的八倍,求另一个数. 如图,AD//BC,AB//CD,MN=PQ,求证DE=BE 帮我写周记给分不要写雪 世界上到底有没有鬼这类的东西啊 有太多无法解释的事了! 如图,MN平行PQ,同旁内角的平分线AB,BC和AD,CD相交于点B,D,(1)求证:AB垂直BC(2)求证:四边形ABCD是矩形 上海市奉贤中学我能上吗?我现在户口在浦东新区,我妈妈想把我的户口迁到奉贤青村镇,我在长岛中学读初二,排名在年级前十左右(100分的卷子四门平均92左右,数学大概95左右)古筝7级,女,我 解方程组2x+3y=240 x+2y=150, 猪笼草里的液体是由哪几个部位构成的 “自从我上中学以后‘’用英语怎么表达 '奇妙'是什么意思了 神奇古怪草 猪笼草种得出来吗这个是假的吗 中学同学用英文怎么说啊?美国人真是的! “很神奇”有什么特别的意思? 1、A除B的商是2,则A∶B=( )∶( ).1、甲数的5/8等于乙数的5/12,甲数∶乙数=( )∶( ).RT 英语翻译 求1.2.3. 已知甲数除乙数等于16,把甲 乙两数同时扩大2倍,商是 英语翻译 一列火车在平面的铁轨上行驶,由于遇到紧急情况,火车以速度v(t)=5-t+55/(1+t)紧急刹车至停止.求 (1一列火车在平面的铁轨上行驶,由于遇到紧急情况,火车以速度v(t)=5-t+55/(1+t)紧急刹 乙数除甲数商是0.24,甲乙两数最简比是?( )×12=6/11 5×( )=1/4 1÷( )=2/7 =IF(ISNA(VLOOKUP($A$1,订单台帐!$A:$U,12,FALSE))," ",(VLOOKUP($A$1,订单台帐!$A:$U,12,FALSE)))详细的解释三个函数(IF,ISNA,VLOOKUP),它们各自的公式、意思及整体的意思. 火车经过12.5米的钢轨的时间是1.8秒,求火车的速度 有一个梯形 上底是3.14 下底是4.19 腰都是15 求面积
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘