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

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

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

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

你是如何遍历数组中的元素的?20年前JavaScript刚进入视野时,你应该是这样写的:

for (var index = 0; index < myArray.length; index++) {     console.log(myArray[index]); }

直到ES5中原生JavaScript中添加了forEach方法:

myArray.forEach(function (value) {     console.log(value); });

语法上简洁了一些,但是它有一个小小的不足:你不能用break语句跳出循环且不能在这个封闭的函数内使用return语句。

如果有一个简单的for-loop语法来遍历数组就好了。

使用一个for-in循环怎么样?

for (var index in myArray) {     // don't actually do this     console.log(myArray[index]); }

我用几个理由来说明这并不是一个好主意:

  • 数组的索引值index是String类型的“0”,“1”,“2”等等,而不是Number类型。当你进行算术运算时(“2”+1==“21”)也许并不是你期望的结果,所以运算前需要类型转换,这很不方便。
  • 循环体不仅会遍历数组的元素,甚至连expando属性也遍历出来了。举个例子,如果你的myArray数组中有一个叫做name的属性,遍历时就将 index ==”name”也遍历出来,这样就多了一次执行。即时这些属性在数组的原型链上是可直接访问的。
  • 最让人无语的是,在某些情况下,这段代码在遍历数组元素时顺序是任意的。

总而言之,for-in语法是被设计来遍历普通的“键值对”对象的,不适合用在数组上。

强大的for-of循环

还记得我上篇提到的ES6是向后兼容的吗。即使在遍历数组的时候,成千上万的网站使用了for-in循环。所有“修复”for-in让它更适用于数组是有必要的。ES6来解决这个问题的唯一途径是新增一个新的遍历语法。

新语法如下:

for (var value of myArray) {     console.log(value); }

恩?!从构建上来说好像并没什么改变,事实如此吗?当然不是,我们来看看for-of的葫芦里究竟卖的什么药。首先,只需要注意这几点:

  • 这是目前遍历数组最简洁和直接的语法;
  • 它避免了for-in的所有缺陷;
  • 与forEach()不一样,它支持break,continue和return。

for-in循环用于遍历对象属性。

for-of循环用于遍历数据——比如数组中单值。

其它集合也支持for-of

for-of循环不仅仅是为遍历数组而设计的。基本上所有类数组对象都适用,比如DOM NodeListS。

也能用在字符串上,它将字符串当做一个Unicode字符序列:


它也能用在Map和Set对象上。

哦,不好意思,你没听说过Map和Set?没关系,他们是出现在ES6中的新成员。有机会我们会写个完整的关于它的文章。如果你使用过其它编程语言中的maps和sets,那么你也不会有陌生感。

例如,一个set对象使用于排除重复项:

// make a set from an array of words var uniqueWords = new Set(words);

如果你想遍历你的set,很简单:

for (var word of uniqueWords) {     console.log(word); }

Map有一点不同:它里面的数据由键值对组成,所以你需要使用destructuring将“键”和“值”解构为两个独立的变量:

for (var [key, value] of phoneBookMap) {     console.log(key + "'s phone number is: " + value); }

Destructuring(解构)也是ES6的新特性,在未来博客中会有很多关于它的文章。

目前为止,你可以这样理解:JS已经有了几个不同的集合类,而且更多的集合类正在被添加进来。for-of循环语句的设计初衷就是适用于所有这些集合类。

for-of并不能用于普通的旧对象。如果你想要遍历对象的所有属性,可以使用for-in,也可以通过Object.keys(object)将对象的所有属性以数组形式返回后再使用for-of。 

// dump an object's own enumerable properties to the console for (var key of Object.keys(someObject)) { console.log(key + ": " + someObject[key]); }

深入理解

“能工摹形,巧匠窃意。”——巴勃罗·毕加索

JavaScript在ES6中所新增的特性并不是凭空而来,大多数都是借鉴于其它优秀的语言。

以for-of循环伪例,与C++、Java、C#和Python的循环语句非常类似。和它们一样,支持该种语言提供的多种数据解构和标准库。但是它也是该种语言的一个扩展点。

就像for/foreach语句在其它语言中一样,for-of的执行完全靠方法调用。像Arrays,Maps,Sets等我们提到过的对象都有一个共同点就是它们都有一个遍历的方法。

其它类型的对象也都可有一个遍历方法:任何对象都可以。

就像你可以对任何一个对象添加方法myObject.toString()让JS知道如何将对象转换为字符串一样,你也可以对任何对象添加方法myObject.toString()来告诉JS如何遍历这个对象。

例如,假设你使用的jQuery,尽管喜欢使用.each(),那你也会喜欢上在jQuery对象中使用for-of。请看下面这个例子:

// Since jQuery objects are array-like, // give them the same iterator method Arrays have jQuery.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

好吧,我知道你会觉得[Symbol.iterator] 这样的语法看起来很奇怪。它是怎么执行的呢?使用方法名就可以了。标准委员会刚刚将这个方法命名为.iterator(),但是你已存在的代码中可能已经有了叫做.iterator的方法,那会造成命名冲突,让人傻傻分不清。因此所有标准库将其封装进了symbol,而不是使用简单的用字符串来直接命名。

Symbols是ES6的新特性,我们将在以后的博客中讨论它。目前,你所需要知道的是现在标准定义了一个全新的symbol,比如Symbol.iterator,为了保证与已存在的代码不存在命名冲突,所以这个代价就是语法看起来有点奇怪。

为了这个优秀的新特性的向后兼容性,这点小代价也就微不足道了。

迭代器对象

从现在开始你再也没有必要为自己写一个迭代器对象了,这个我们在下篇文章中再来讨论。但是出于完整性的考虑,让我们先来看看一个迭代器对象是什么样子的。(如果你跳过这一节,你会错过很多有趣的技术细节哟)。

for-of循环开始于对集合的[Symbol.iterator]()方法的调用。它会返回一个新的迭代器对象。任意一个有.next()方法的对象都可以被称作迭代器对象;每次执行进入循环时,for-of方法将会用.next()方法。例如,下面是一个我所能想到的最简单的迭代器构造:

var zeroesForeverIterator = {   [Symbol.iterator]: function () {       return this;    },    next: function () {        return {done: false, value: 0};    } };

每次当.next()方法被调用的时候,它会返回相同的结果,告诉for-of循环:(1)我们还没结束迭代;(2)下一个值是0。这意味着,(value of zeroesForeverIterator) {}将是一个无线循环。当然,一个真正的迭代器并不会这么简单。

迭代器的设计,伴随着.done和.value属性,从表面上来看似乎和其它语言中的迭代器不太一样。在Java中,迭代器将.hasNext()和.next()区分为两个方法。在Python中,它只有一个.next()方法,当没有下一个值时会抛出StopIteration 。但是从根本上来说,这三种方法返回同样的信息。

迭代器也可以实现一些可选方法,比如.return()和throw(ext)。在for-of循环中,当遇到异常或者break和return语句时可以调用.return()方法提前退出循环。迭代器可以通过实现.return()方法来清空变量或释放当前资源,大多数迭代器对象是使用不到这一点的。.throw(exc)是一个特殊的例子:for-of完全使用不到它,我们下次再来讨论。

现在我们已经了解了所有的基本细节,我们可以写一个简单的循环并重写它的底层方法调用部分。

先写一个for-of循环:

for (VAR of ITERABLE) {     STATEMENTS }

下面这段代码使用简单的底层方法和几个简单的变量来实现同样的功能:

var $iterator = ITERABLE[Symbol.iterator]();var $result = $iterator.next();while (!$result.done) {  VAR = $result.value;  STATEMENTS  $result = $iterator.next();}

这段代码并没有体现出.return()操作。我们可以添加进来,但是我认为认清它的执行过程比阐明它更重要。for-of的使用起来很简单,但有很多看不见幕后的工作。

我什么时候才能使用它?

当前所有的Firefox releases版本都支持for-of循环。如果你想在Chrome中使用,到chrome://flags设置“Experimental JavaScript”为“开启”即可。微软的Spartan浏览器支持它,但是IE不支持。如果你想要在Web中使用这些新语法且不用考虑支持IE和Safari,你可以使用Babel或者谷歌的Traceur这样的编译器将你的ES6代码转换成兼容性友好的ES5。

在服务端,你不需要一个编译器——你可以在io.js(基于Node,是一个不错的选择)中使用for-of。

(更新:在Chrome中默认是禁用的,这个被我忽视掉了,感谢Oleg 指出。)

讲完啦!

我们今天的计划都完成了,但是我们对for-of循环的学习还没结束。

ES6中还有一个和for-of完美结合的新对象。我之所以没提到它是因为它是我们下次的主题。

我认为它是ES6中最神奇的新特性。如果你之前没在像Python和C#这样的语言中使用过它,一开始它可能会让你感到难以置信。无论在客户端还是服务端,这是写一个构造器最简单方法,对于重构很有用,它有可能会改变我们写异步代码的方式习惯。

下次将一起深入ES6的generators 。(译者:向渝 责编:陈秋歌)

原文链接:ES6 In Depth: Iterators and the for-of loop

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

相关阅读:

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

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

【OSTC讲师专访】Debian开发者李道兵:平静地理解开源 红帽推出开源业务流程管理套件:JBoss BPM Suite 6 科学研究证明:程序员快乐才能更好的工作 ChocolateChip-UI:能“逆转”的跨平台应用开发框架 分享12款最佳的Bootstrap设计工具 Apache Flex 4.12发布,支持iOS 7 智能手机应用挑战Web平台,看W3C如何反击? 电信级数据流量与监控系统部署案例分享 TCL联手Mozilla,HTML5智能电视真的要来了! 先睹为快:Unity亚洲开发者大会虚拟游览展示 OSTC&#183;2014 演讲日程出炉,Perl创始人来了! Unity将收购Applifier,并引入Everyplay和GameAds两大平台 《近匠》从Cubieboard到radxa:汤亮的第二次硬件创业 九头蛇与大象之争,Hydra或将取代Hadoop 喜讯:中国安全团队Keen成功在Pwn2Own 2014黑客大赛上攻破64位Mac上的Safari OCP黑客马拉松冠军:24小时头脑风暴背后 新时代应用程序设计及MongoDB的十个深入理解 借助“开源”东风 英特尔打造卓越“软实力” 深圳综合交通设计研究院张鹍鹏:智能交通设备领域已成红海 信息化是发展趋势 25个可遇不可求的jQuery插件 Web设计中对视差设计的误区 直接拿来用,九个超实用的PHP代码片段(二) 一周消息树:小米染指平板电脑凶多吉少 移动周报:Xcode 5.1更新、CarPlay揭秘,Apple很忙 可穿戴领域,创业公司的掘金点?还是滑铁卢? 搜狐SendCloud2014运维技术沙龙拉开帷幕 一周热点:选择Go语言的12个理由,九头蛇与大象之争 中国云计算大会PPT集萃(二):十位技术大牛分享平台打造技术 延迟250毫秒损失数百万美元,Hadoop系统该如何应对实时任务 IBM成立展示中心扩展大型主机的Linux开放生态系统 SDN解决方案总结:OpenFlow、虚拟机、OpenStack和VXLAN/NVGRE 谁还来个高程QQ群? 大家都上过哪些收费电影下载网站? 请问那里有好的中文输入法下载。我的是redhat72 在线等待----100分,急!!! 光标定位问题 asp mail question 一些比较菜的问题 实用问题,在触发器中如何退出? 怎样来通过我的程序来控制另一个程序的下拉菜单 VS 2003哪里有下?VB的GRIDCTRL如何调整各列的宽度? 请问如何把datagrid中的数据到出到Excel中做报表 DLLHOST.EXE是什么东西?它占用了CPU的99%,服务器慢如蜗牛,ASP文件不能正常运行,救命啊!!!!!! 急用!谁能提供五子棋的算法和设计? 谁有无限制的activethread控件,通知一下, 很急! 谁能提供五子棋的算法和设计?急用! 请教一个WebLogic问题,请高手帮忙! 怎么知道DLL里函数以及它的参数 有关IE主页被恶意修改的问题请教。。__急! 急用!谁能提供五子棋的算法和设计? set mail=server.createobject("cdonts.newmail") 错误,高手指点一下!!! 谁能提供五子棋的算法和设计?急用! 如何解决??? UNIX中文录入的问题 菜鸟求一个语句 500分给前辈 大家都来看看这些女人(三分长相,七分打扮) 兄弟们,帮忙提供个参数~送100分了,承蒙关照了 调查:你现在用哪种开发工具,感觉如何? 防火墙经常出现类似记录信息 请问.pdg格式的电子图书如何浏览 新版net2003web Service 奇怪的FileNotFoundException错误 求救:支持汉字的OCR控件。给个制作思路也成。 在网络中运行in.readline 的时候会不会等待有流传来才读取的??很矛盾 ODBC的作用?=我的机器上没安任何数据库管理系统(如:access,foxpro等)但我可以用asp访问某个.mdb文件,是吗? 怎样用程序实现把FTP站点映射为一个驱动器? 虚拟光驱是怎样做的? //非常奇特的系统启动现象,进来看看// 有没有这样的涂鸦板的代码 //非常奇特的系统启动现象,进来看看// //非常奇特的系统启动现象,进来看看// //非常奇特的系统启动现象,进来看看// 请问各位大虾,JSP服务器使用j2ee的多不多??? 为何crystal report4.6打印出来的纸张长度大于预览时的长度 怎样实现? 听在迈普(maipu)的同学说,在这学期的毕业实习里,很多新人被开掉了,为自己的想象力惭愧 在datagrid模板中绑定的label控件怎么解决显示文本宽度的固定 有点困惑! add() mssql中如何将字段类型设为“布尔”类型? 麻烦高手给我说VC++和标准C中不一致的地方 我的明天何去何从! y=(3-cosx)/(3+cosx) 最值y=3-cosx/3+cosx think you are very crzy! who is pig? 1 1 1 1 这个该怎么算到24点呀太难了 好久没做忘了( 一元二次方)(2x-1)的平方=(3-X)的平方 who is the author of three little pig 关于感恩的心的手抄报 含ow的单词 itouch里的 who is pig怎么玩 关于感恩的心的名言 与瞧不起意思相近的两个字的词语不能是鄙视和歧视 热和雨能组成什么成语 今年产梨大丰收,年产量达到3.6万吨,比去年增产两成,去年产梨多少万吨?要列式 数学选修2—2麻烦解释下 向来很久 我不会英语,别人给我发短信好像是骂人的,谁能帮我译下,The man who is reading the message is a pig 积分 (cos3x-cosx)^2 函数f(x)=x2+2x+5在[t,t+1]上的最小值为g(t),求g(t)的表达式.函数f(x)=x 2 +2x+5 在[t,t+1]上的最小值为g(t),求g(t)的表达式 . 1.用五点法作函数y=3sin(2x+π/3)的简图,并求使函数取得最大值的自变量x的集合.2.在ΔABC中,角A、B、C所对的边分别为a,b,c,且cosA=1/3(Ⅰ)求sin^2 B/2+C./2+cos2A的最大值;(Ⅱ)若a=tan60°,求bc的最大值; 请问cos3x/2+cosx/2怎么化简? 描写路途辛苦的成语 《令人高兴的变化》为题写一篇作文 弘扬雷锋精神的活动感想要怎么写? ppt中点一次出来第一个标题,再点一次出来解释此标题的内容,再点一次隐去以上解释内容并出现下个标题.以上过程在同一张幻灯片中完成,这是怎么做到的,研究了老半天没研究明白, 高一上学期期末数学考试题目,急求答案,要过程.求经过2x+y+8=0和x+y+3=0的交点,且与直线2x+y-10=0垂直的直线方程.过程答案,谢. 复兴镇今年大丰收,年产24万吨,是去年产量的五分之六,去年这个镇产香梨量是多少万吨 感伤的风搭配着苦涩的Coffee,在宁静的夜晚里,你有什么样的感触呢?静静的享受音乐的描述…… 我由此想到,老师们在平凡的教学岗位上付出的一切不会是徒劳的.这句话的意思 2sin2xsinx+cos3x如何化简 猜猜1+1=? 这题怎么算?然后答案是什么 要画一个面积为18平方厘米的矩形,使它的边长之比为2:3,它的边长应取多少? 手抄报感恩的心内容,要少一点,5个以上,不要老师的! 怎么算?答案是什么 已知a=1/根号5-2,b=1/根号+2,求根号(a^2+b^2+7)的值. 内洞一团漆黑,什么也看不见是什么成语 这个图有几个角,几个直角? 如图,将矩形纸片 abcd沿其对角线折叠,使点b落到点b'的位置,ab'与cd交于点e. 结拜 程序 磕头 磕几个,谁有详细的程序!烧香 3根香?磕头 磕几个?还是3跪9拜?盟誓喝酒规矩是这样么 请问还有详细点的没!要割手指啊是洒酒 还是喝酒? 这道题怎么算?、我等着要答案.谢谢 关于《匆匆》的名言 摩托车三小时行135千米,汽车每小时行65千米.摩托车每小时比汽车慢多少千米? 图上有几个角,几个直角! 名人名言;复恐匆匆说不尽,下一句是? 设f(x)=x^2,0≤x 中共在50-70年代社会主义建设中的失败教训和原因?请尽量具体一点! 十分钟之内.答的好追加.一道二次根式题.看不清的地方统统是2次方.答案是2a分之(2+a)倍的根号下2a. 读[əu]含ow的英文单词有哪些?越多越好! I'm often ill.M_______I hardly ever exercise空格上填以M开头的单词 感恩的心手抄报的内容 与low的ow发音相同(字母相同)的英文单词 His father hardly ever exercise.变成反义疑问句、 如图,将矩形纸片ABCD沿对角线AC折叠,使点B落到点B’的位置,AB'与CD交于点E.(1)试找出一个与△AED全等的三角形,并加以证明.(2)若AD=5,P为线段AC上的任意一点,PH⊥EC于点H,PG⊥AE于点G,试求PG+PH 匆匆片段的阅读求答案 有the big stick这项政策吗 6.如图,将矩形纸片ABCD沿对角线AC折叠,使点B落到点B′的位置,AB′与CD交于点E.若AB=8,DE=3P为对角线AC上的动点,PG⊥AE于G,PH⊥DC于H.设PG的长度为x,PG•PH为y.则y的最大值是(  )  A. found,mike,notebook,english,in,an,school,library,the,this,afternoon,.连词成句. hardly ever的同义词是什么? 求y=(cosx-3)/(cosx+3)的最值 什么狗好 四个角都是直角的图形是平面图形,理由 埃及多地爆发大规模反对军方游行【高清环球时报专访中国赴叙利亚参加化学武器会议记录爆奥巴马医改网站开通首天仅6加拿大女子相亲网站“钓男人”吃免费餐梅德韦杰夫谈监听丑闻:美国不能这样厚俄“彼得大帝”号核动力巡洋舰进入地中韩国三四流整形医生赴中国淘金 自称顶近二成美国人称见过鬼 女性比男性更易男子把鸡蛋强塞女子下体后捏碎性侵 辩短短数小时吸金近万 黑采砂船疯狂吞噬双十一:你的订单支付没成功 收到这样平阳孕妇横穿马路被撞倒 村镇干部施救暖湿气流hold住全场 浙江未来一周西湖国际马拉松周日开跑 周边公交线路中国100大最佳市政府出炉 浙江9个近二成美国人称见过鬼 女性比男性更易默克尔遭美国监听 德议员称斯诺登愿协美墨边境现毒品走私隧道 地下10米深新书披露奥巴马曾很怕应酬克林顿 不愿会议记录爆奥巴马医改网站开通首天仅6斯诺登与德议员会面三小时 向德联邦政日照:粗心父母着急回家过年 倒车压伤无证无牌酒驾 烟台一司机爬到警车下声济南爱心墙“供需两旺” 市民盼义工团德州:偷手机换酒喝 健忘“酒鬼”盗窃“文化中国·四海同春”登陆悉尼网传“美瞳会掉色” 实验:两款黑色隐日照:套牌车撞翻环卫工致骨折 肇事者重磅!中央定调一件大事,将影响7.5下跌已成定局,各产油国将如何?新年继续寻找新动力丨社论叙利亚的下一步这场“石油战争”,各国都在盘算什么?来,叫你的孩子,别太懂事有毒的母女关系怎样影响女儿一生?李根谈“垫脚”:向孙悦道歉亨利:梅西如野兽,杀戮似无敌再现误判,C罗进球越位在先华为推笔记本会抢了联想饭碗吗?你怎么德波尔:巴佐尔很难拒绝巴萨年的故事冯唐版《飞鸟集》自绘插图
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘