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

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

《近匠》第07期,专访《恶魔塔防》团队,看俄国复杂深奥的游戏文化 代码托管网站GitHub的总裁和CEO进行职位互换 使用Chromebook的五个指南 云中游终极声明:热酷侵权,有种正面回答少打太极 背后故事:英特尔Edison中国研发 内部评审中曾三次被拒 全栈工程师会是未来的发展趋势吗? 大数据整理:囊括分片、存储方法、扩展等多个方面 物联网 ,下一个云计算市场 一位数据挖掘工程师眼中的“大数据与企业的数据化运营” 揭开“iOS in the Car”的神秘面纱 与Apple对峙:法律途径,并非是我想要 Halfbrick新作市场表现低迷:前作辉煌难续 专访豌豆荚:融资,会给技术团队带来哪些影响? 前端开发必备 40款优秀CSS代码编写工具推荐 新环境下的新体验是互联网硬件火热的根本原因 信息安全救星 ——变形代码产品ShapeShifter AWS启动大规模降价,引领行业降价潮流 Windows 8.1 Update 1最新版的截图再遭曝光 2013年软件领域因缺陷导致的五大事件 专访AMD技术高管 详解Kaveri技术性能及新开发特性 网络的东西南北:从SDN到网络虚拟化 Bug让Chrome浏览器成了窃听器 联想23亿美元收购IBM X86服务器硬件及服务 Mozilla联手富士康推出Firefox OS平板 基于Web提供服务 GitHub中国游记最终回——开源与车库的碰撞 学以致用,光棍极客通过大数据搞定女朋友 1月24日:Mac步入了而立之年,生日快乐! 微软2014财年Q2财报:Surface营收翻倍 趣文:假如编程语言在一起聚餐 AOL收购个性化服务公司Gravit,耗资9070万美元 谷歌三月将办Pwnium 4黑客大赛 奖金高达271.828万美元 英语真的那么重要吗? 一个JS的简单问题,但是我还是给100分 怎么透明显示一张bmp图片(急,在线等待) 急,两个问题,帮帮忙(其中一个关于ActiveSkin) 查询出的报表内字段值为空的单元格,显示不出单元格框线,为什么? Java论坛 急!在LINUX下,配置内核时Intel corporation|82801AB AC'的声卡应该先哪项,我用的是2.4.16的内核。 世界杯——蓝色的忧郁 使用异步socket通信,服务器端在OnReceive消息函数中能否获得客户端IP地址? 菜鸟学JAVA送分 怎样用delphi实现EDI? 两到汇编题。麻烦大家帮我做一下。。我实在做不出来 今天去面世了~~~结果他们………… 举报 哪里有.net源程序下载?? : 两到汇编题。麻烦大家帮我做一下。。我实在做不出来 莱鸟问题:如何字符变量str的值赋给EDIT控件, : 两到汇编题。麻烦大家帮我做一下。。我实在做不出来 哪里有2001年的中程的试卷? 第一次来CSDN,以后希望大家多多帮助!! 在VB中获取和修改计算机名字 用什么软件能把扫描仪扫的文章变位文本文档?? 终止线程出错! VB中远程数据库的访问 如何实现使textbox中只能输入带两位小数的内容?即保证其中内容为*.XX(*代表任意数字串),凡不合要求的输入都被过滤? 如何在IIS的DefaultWEB Site的属性的HTTP Header中加入新的File type?? 怎样读jpeg的头文件,用C语言,谢了 为什么我远程连接sql server总不成功呢?我已经把1433端口开了啊 西游记 如何判断一个大整数是素数,如何找出整数的模逆 多层数据库开发源码大公开---不可多得! WinZip等的右键菜单Add to xxx.zip是怎么实现的? 帮帮忙,急! 因写程序丢过头发的请进. 怎样使lable的内容分两行显示 一个使我困惑的小问题,敬请关注(***100分***)!! 帮帮忙好吗? 二个关于字符串中对子串的替换与删除的问题? 怎样实现虚构造函数? 请问各位高手,手机图片和手机铃声是什么格式的?在电脑上能不能打开?应该怎么制作? 请大家帮个忙,有个小问题,如何用showmessage输出括号内的内容('%K%')?在线等待 A simple problem!? 救命,对话框显示的奇怪问题!!! An error 1069 (由于登录而无法启动服务器) 请问为什么向Oracle表里加不上记录? 我在局域网中用些东西常被主机防火墙隔了,有什么办法绕过防火墙 谁有MPEG-LAYER3的详细资料或连接? 我用一些软件如音乐大师等,一打开程序,该程序窗口就被关闭了,而在光盘上进行都可以? 如何判断一个大整数是素数,如何找出整数的模逆 怎样使用C#做互相通信的client/server程序 总人数除以平均每人种植棵数等于? what does your father look like?同义句what does your father look like?what____your father______? 某年级有135人,组成3个小组参加劳动,第一组与第二组的人数之比是2:3,第二组与第三组的人数之比是6:5求3个小组各有多少人? ____do you like better,apples or oranges是什么意思 猪+羊=40千克 狗+羊=38千克 猪+狗=42千克.球三种动物的重量各是多少千克? 甲乙两车同时从两地相向而行,当甲车行了全程的60%,乙车行了全程的75%,且两车相相距70千米,求两地距离 Do you like apples 的中文是什么呢 动物的天敌 甲乙两车同时从两地相向而行,当甲车行了全程的65%,乙车行了全程的75%时,两车相距60千米,两地间路程是多少千米? 求我被同桌摸了奶作文,800字左右. 属鸡和属狗属猪的关系怎么样? 甲乙两车同时从两地相向而行当甲车行全程的65%乙车行全程的75%时两车相距60千米两地间的路是多少千米要写算式哦 What’s your sister like?—_______.A.She is a worker\x05B.She likes pearsC.She is very thin\x05D.She is like her father —只猪等于三只狗—只狗等于八只鸡—只猪等于几只鸡 2倍,两个年级各有多少人? Sir you an apple juice中文什么意思 What does your sister like?和What is your sister like?有什么区别?我查了一下,有的说他们都是“你姐姐长得怎么样?”的意思,也有的说”What is your sister like?是你姐姐喜欢什么“, 2倍,两个年级各有多少人?【用方程解】 关于《牛奶与健康》的作文内容要求:主题鲜明.内容健康,构思新颖,富有童真、童心、童趣.作品要求通过对牛奶的认识.饮奶过程中的故事,对提高身体素质、智力水平、学习成绩的作用等展开 盒子里有同样大小的红球和白球各8个,至少要摸出多少个球,才能保证取到两个颜色相同的球?列示 2倍,两个年级各有多少人(用方程解) 教室里的一场风波 作文 500字急 求牛奶与健康的作文,谢谢啦 有一座粮仓,先把比存粮总数的5分之2少23吨的粮食运走,然后又运进143吨,此时粮仓存粮比原来增加了15%,粮...有一座粮仓,先把比存粮总数的5分之2少23吨的粮食运走,然后又运进143吨,此时粮仓存 《——的风波》作文,500字以上 牛奶营养健康作文 一座粮仓,先把比存量总数的少33%的粮食运走,然后运进143吨粮食,这时粮仓存量比原来多了25%,求原来几吨 插头有三根线,插座有两个孔,请问我的地线该连接零线还是火线 she likes this coat 改为否定句是 鹰的叫声该用哪个拟声词表示?要最像的那种 热水器的插座电线中 黑色 绿色 白色 三根线 哪根是火线哪根是零线 哪根是地线? She likes this coat改为否定句是什么? She teaches English in Shanghai 改为否定句 水塔里有细细的小虫是什么虫?对人体有害吗? 列举中国近代史上的反抗事件 5列 狼因为愤怒而发出的声音的象声词是什么 一个圆锥形沙堆地面积是12.56平方米高9m把这多沙子放入长5米宽2m的沙坑可以铺多厚 列举中国近代史上(五四前)9个重大历史事件,并分别写出它们的影响? 象声词:虎( ) 狮( ) 象( ) 狼( ) 犬( ) 乌( ) 猿( ) 蝉( ) 马( ) 鸡( ) 小孩几岁才能上小学一年级, 请列举中国近代史上与南京有关的三个历史事件. 有一座粮仓,把粮仓的5分之3运走,然后运进176吨粮食,这时粮仓的总数比原来增加了15%.粮仓原来有多少吨 一圆柱形沙堆,店面积是12.56立方米,高0.9m,把这堆沙子铺入长4.5m.宽2m的沙坑内,可以铺多少米?保留两位小数~ 大家帮忙罗列一下中国近代史上的时事报道 有一座粮仓,先把存粮总数的2/5的粮食运走,然后又运进176吨,这时,粮仓存粮比原来增加了15%.粮仓原来存粮多少? 1只小狗的重量相当于2只小兔的重量,1只小兔的重量相当于3只小鸡的重量,那么1只小狗的重量相当于()只小鸡的重量 两个或多个动名词短语并列作主语的时候 谓语动词是单数还是复数形式例如 Watching TV and reading books are really interesting是不是应该这样 使用复数 It ____(look) like rain,doesn`t it? 364只碗三人共食一碗饭,四人共吃一碗羹 ( )you like apples A,Can B,Do C,Are 动物是怎样对付天敌的要说什么动物怎样对付它的敌人 一寺院有364个碗,三人一碗饭,四人一碗羹,正好用完所有碗,用方程式求寺院多少 五月份的产量比四月份的产量多5分之1,五月份的产量是四月份的多少 求中国历史爱国人物及其简要事件~只要用一句话概括就可以~形势为 谁谁谁什么怎么样比如:朱自清宁可饿死也不令美国的救济粮.要至少10条, 两只狗的重量等于4只兔子1只狗的重量,问1只狗和多少只兔子的重量相同. What does your sister do?(同义句转换) ____ _____your sister 在中国历史中有谁是那么爱国的人和事? 某寺不知有多少和尚,但知道他们三人合吃一碗饭,四人合吃一碗汤,共用了364只碗,试求和尚的人数.今天一定得答完!... What does your friend look like?改为同义句 某乡有一座粮仓,运走总数的五分之二,又运进176吨,这时粮仓的存粮比原来增加15%,粮仓原来有多少粮食
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘