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

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

角逐Hadoop市场,Cloudera与Hortonworks竞争白热化 OpenStack将提供对Docker的支持 Facebook Q1财报:营收25.02亿美元、59%来自于移动 黑客们盯上了卫星,IOActive的惊人发现 开发汽车应用之前,你必须了解的7件事 埃森哲:智能电视潮流,势不可挡 直接拿来用!Facebook移动开源项目大合集 高大上Hadoop技术培训:Hadoop在企业中的应用实战 【走近讲师】新浪丛磊:通过MAE构建企业内部私有PaaS平台 API增长新趋势 消息应用类独占鳌头 软件项目为何会失败? 严澜:搭建高可用的MongoDB集群(二) 微软、思科、Google、Facebook等联合推出CII 狙击“Heartbleed” 这是个神奇的国度:细数五大印度裔IT牛人CEO Atmel CMO Sander Arts眼中的创客运动 Unity“三巨头”:全心全意为开发者服务 全球移动广告现状报告:哪种平台、应用最赚钱? 《近匠》Smart Wallit,钱包找不到了?给它“打个电话”吧 Mozilla新CTO:JavaScript、 Firefox OS专家Andreas Gal 李彦宏发布百度大数据引擎,及与谷歌、亚马逊等类似项目对比 大数据领域,实时打击欺诈犯罪的4个战场 一周消息树:谷歌Project Ara,将开启下一个智能手机时代 数据恢复服务商的6个最佳实践 【走近讲师】谭晓生:魔高一尺道高一丈,360基于大数据的网络攻击检测 一周热点:摩尔定律让位于贝索斯定律 阿里巴巴集团CTO王坚确认出席第六届中国云计算大会 【走近讲师】青云甘泉:混合云的构建及其对企业的帮助 RadiumOne创始人兼CEO因家暴被公司解雇 3D打印狂潮:可检测皮肤疾病的低价手机显微镜 浅谈导航设计,开发者必备的十大实用技巧 【云先锋 41】上海越诚:基于云服务的建站类iService软件超市 ===============想知道111222去向的朋友,看这(独家披漏)===================== 以下SQL语言如何写? 111222走了~~送分~~~心里不好受~~~ 111222真的走了~~~~~~~~~~~ JBuilder中用MYSQL数据库,用中文进行条件查询时,查不出任和数据? ASM 菜鸟问题,请大家帮忙!谢谢 解释一下好了吗? ============答对我的问题者,将可获得111222的签名照片!!!!!!!!=========== 关于图片的上传 ======== 绝对好消息,activereport2.0已经release 了,cracker们出动啊~~~~~加油 ============= 关于什么才是真正的系统分析和系统分析员的讨论!——欢迎大家参加,进行善意地讨论!^&^ 今晚的球赛什么时候开始啊? 哪里有关于水平考试(高程)的模拟题的啊??? 为什麽还是不能显示中文呢? 怎样获取WIN2000的密码 在父窗体怎样画jpg格式的背景图? 如何注册MSComm控件????????? 如何解决这个问题啊?重赏啊!!!! 公告: 从现在开始封shines 111222 :)流芳斑主,结贴的工作要开始了,会很累啊!我代表大家先谢谢你了! 怎样改变MSHflexgrid中每条记录的背景颜色。急急急急急急急 各位,能不能给我讲一下“句柄”是怎么一回事? 唉,心情不爽 关于C++语法的问题? 灌水-----大学时的恶作剧(转载) "setdibs()"是什么来着,请指教,谢谢! 写注释不宜过头 这段代码错在哪里? 请大家预测一下比分(参与者都有分)开赛后就不算了,还有半个小时,赶紧着 写网络电话程序的讨论 最后一帖,贴完睡觉----如何在电梯里捣乱 怎样定制一个在程序中重用的组件?只能通过包方式吗? 寻寻觅觅 汉英计算机科技文章 互译!!有劳各位朋友费心帮忙找找 我靠!真TMD不爽,这个时候准老婆的老妈进了医院! 怎样调用*.db格式文件 谁知道哪儿有英汉互译,急急急急!!!! ISO 9001认证 VS CMM2 谁知道哪儿有《神秘的人月》下载? 为111222求情 怎样可以修改浏览器的标题? 怎样可以修改浏览器的标题1? 哪位能给我一个source insight 3.0的sn号? 怎样可以修改浏览器的标题2? 如何异步调用远程组件的方法? 哈哈!球赛开始了!我也不想去医院了!!!顶多明天挨顿骂! 上CSDN的有谁是七月份毕业,大家认识一下 我想问问,一个程序员的黄金年龄是多少? 如何由CRgn得到一组Polygon? 初学者请教一个小问题!急急急,尿都快急出来啦! 急急急急急急急急急急,用vb怎样知道COM口是不是打开着,能不能不用控件高分. 高手请看:20 分 我想给50 分,但是系统只让给20分,对不起大家了,有机会一定补上!!! 8.5x-3.5x=27.5 求方程 2(x-2. ..二元一次方程组...有一些苹果箱,若每只装苹果25千克,则剩余40千克无处装,若每只装30千克,则余20只空箱,这些苹果箱有多少只?请列式计算...PS...符号"^"表示上标..即N次方...每个方程组之间请 0.1(X+2)-0.9=0.5这个方程怎么解 8(X-6.2)=41.6 (X-3)/2=7.5 这两个方程怎么解 列二元一次方程组解2道初中数学题1,一旅馆的客房有3人间和2人间,3人间每人每晚25元,2人间每人每晚35元.一个50人的旅游团到该旅馆住宿,租住了若干客房且每个客房正好住满,一天共花住宿费1 ×的2.5倍比它的1.8倍多9.8.求方程的解 帮忙解一道方程,x-18=3(x-26) 初中数学二元一次方程组题一个两位数,个位数字比十位数字大5.如果把个位数字对调,那么所得到的新数与原来数的和是143.求原来的两位数 方程:6乘9+3x=70怎么解? (x-2)/(x+2)+16/(4-x^2)=(x+2)/(x-2) 初中数学题(有关二元一次方程组~急)1.若|X+Y-3|+(X-Y)^2=0,你能求出X,2.已知t满足方程组{2x=3-5t,则x和y之间满足的关系式是_______3y-2t=x, 3x+0.9=3.3的方程怎么解 解一道方程!3分之2(x-y)=4分之x+y-1 6(x+y)=4(2x-y)+16! 初中数学题二元一次方程组 3x-2.4=6.9 方程 第十六题该怎么算?方程式来的. 方程log2 (x+4)=2^x的实数根的个数为好像是两解 x÷250+x÷200=6.75这个方程怎么解, 方程-3x>-6的解是? [(4-x+4)*4/2]+(4x/2)=16 这道方程怎么算 X/250+X/200=6.75 这题方程具体怎么解 请解这个方程:(9×0.7)×3x=1 x+9=2x-9这个方程怎么解 方程8分之1x-4分之1=2分之1的解是() 8(×-6.2)=41.6(方程) 求方程9^2x-1=4^x的解 怎么解x-(6/1x-30)=8/7x这个方程怎样解 (X+1)*6=(X-1)*8这个方程咋解? 方程9^(2x-1)=4^x的解x=RT x-4/1x=(150-x)-30 这个方程怎么解?是四分之一!不是一分之四! 判断题“方程X-1.2=1.6的解是2.8”这句话对吗? 2x—9=x+9(方程解答) x+4分之1x=30怎么解这个方程? 数学判断题:方程5+2x=16.2的解是5.6 x比6分之5=9分之5【比例方程】 20分之1x加30分之1x=1求方程怎么解? 判断题:x=2即是方程式,也是方程的解 解下列方程 15分之4+X=1-15分之4 X-(3分之2+4分之1)=6分之5 x-(8/1+21)+6/1x-4=102这个方程怎么解 怎么做在等式两边都有X的方程,比如说,8X+4=10X,要详解过程哦 3分之2(x+1)=6分之5(x+1)-1++方程怎么解 已知方程3(3x+3)—1=2x的解和3x+m=四分之m—27的解相同!求m的值 方程14+(4.8x-6)-2.8x=8怎么解 8题的方程. 已知方程3(3x+3)-1=2x的解与关于x的方程3m+m=m/4-27的解相同,求m的值. ﹙6分之5+8分之5﹚×x=20分之7(方程加过程) 求救7,8两题拜托用方程解 已知方程3(x+3-1)=2x的解与关于x的方程3x+m=3m-27的解相同,求m的解 列方程,求x的解 输入20,乘6,减去7x输出50 7.8-x=6.2这个方程怎么解 8(x-3)-5x=27类似的方程跪求!有的话给我发十道 列方程式解答:240比X的一半多60.一个数加上它的20%后是8.4,求这个数. 第6、7题用列方程解决. (x-3)+5x=27用方程解 【5+x】*8/2=6哦【列方程, 6、7、8题怎么做直接列方程不用解 8(x-3)-5x=27方程怎么做?完整无误! X+6/5X+6/5X*31/4=320这个方程怎么解 七年级上册数学复习题3答案 速度好急快啊要方程的式子 和答案 6.7.8.9题要过程 急 速度速度速度速度速
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn