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

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

prepend(content)-JQuery API prependTo(expr)-JQuery API remove(expr)-JQuery API wrap(elem)-JQuery API wrap(html) -JQuery API add(elements) -JQuery API add(html)-JQuery API add(expr) -JQuery API children(expr) -JQuery API contains(str) -JQuery API end() -JQuery API filter(filter) -JQuery API filter(expression) -JQuery API find(expr) -JQuery API is(expr) -JQuery API next(expr)-JQuery API not(elems)-JQuery API not(expr)-JQuery API not(el)-JQuery API parent(expr)-JQuery API parents(expr)-JQuery API prev(expr)-JQuery API siblings(expr)-JQuery API Events事件-JQuery API bind(type,data,fn)-JQuery API blur(fn) -JQuery API blur() -JQuery API change(fn) -JQuery API click(fn)-JQuery API click()-JQuery API dblclick(fn) -JQuery API 那裡有用java寫的小游戲的原馬呀﹗﹗ 请问怎才可以让图象中有网格啊? 高手指教 配机!!求助!!(进者有分啊) 这样简单的程序怎么通不过! session值修改还是未解决。 一个问题? flashget怎么用? 怎么相应动态创建的控件的事件 关于多媒体播放器的问题 快结婚了,可男朋友依旧把前女友的照片当成宝贝,我该怎么办? 建议组织一个水园老五大联盟。有支持的请up ! jspsmartupload上传100M以上的文件报错怎么办? 高分求助! 在那里下载jsp服务器的软件? 大家帮个忙,急寻南京兼职,饿死了 在unix下如何编译自己写好的c语言程序? 有个问题请教 ? 保存电脑技巧的问题。 在linux下怎么使用SAMBA使用windows下面的东西? 菜鸟级问题 我要在com+中间层返回sqlserver服务器的时间,怎么通过sql语句实现? 女友是空姐没有安全感怎么办 有几个概念不清楚, 劳驾哪位给解释一下 在unix下如何编译自己写好的c语言程序? Listbox 拖放的问题!解决就给100分! orical 我的测试连接失败! 小问题,别笑! 新手对指针的理解,大家指点指点,多谢!! 重载问题??? 高分求助! 哪里有截取vpn数据包的代码学习啊??? 怎样写贴子的标题才能吸引大家的注意?举例者一律给分! 关于API 为什么我的资源管理器反应很慢? 南京远志科技公司怎么样,马上要去面试了,请大家谈谈情况 请问这是什么意思 100分马上给 升四个▲了,散分!!!顺便问问那些两个星星的,你们升到两个星星以后的心情是什么样的?会不会有些失落感? 谁知道mediaplay控件 有没有直接到 一段视频文件结尾的方法 用quickstart出现地问题 小弟没写过事务,请教下面这个功能怎么写 万分着急! 在线等候!求和问题 怎么在sql server 的存储过程中调用它的异常处理呢? 劳累了一天了,希望在水园的朋友们今晚愉快:) hub上的uplink口跟其他的有什么区别啊? 为什么灌水圆只有回复数,没有点击数!强烈要求显示点击数!同意的近来投票! 帮帮忙 正则表达式,验证TEXTBOX输入的是手机号码,并且textbox不允许空着。 c#里求y=sin(x)怎样实现的?用什么类? 关于UI 线程的奇怪问题,请高手指教 我司有一台高低温箱是-60度的,想知道这种试验箱温度还能做得更低吗? 细胞生长,核糖体的数量增加,物质交换速率增强为什么错( ⊙o⊙?) 摩尔根是什么 哪些是平移现象?荡秋千是平移现象吗?写字是平移现象吗? 布洛维光学硬度计技术参数是什么? 摩尔根怎么样 高低温试验箱做试验的时候温度怎么控制? 胶黏剂的表面张力越大,表面能越低,粘接效果越好,是这样么? 摩尔根的故事 一个质量为m的带电小球,在竖直方向的匀强电场中水平抛出,不计空气阻力,测得一个小球的加速度为g/3,则在小球下落h高度的过程中.下列不正确的是()A,小球的重力势能减少mgh/3B,小球的动能 LC振荡电路中为何当电容中q最小时,电路中I最大?为何当电容中电量最小时,电路中电流最大?希望从过程分析,不从能量角度 当电容电压大于交流电源瞬时电压时,电容是否会放电吗?我想知道电容在交流电的情况下,其充放电的详细过程?还有其串联回路中的电阻电压变化情况及其波形是怎样的? 有一悬线悬挂质量为m电量为q的带电小球,放于水平向右的匀强电场中,设小球静止时西线与竖直方向的夹角为西塔,求;1该小球所带电的电荷电性 2小球受到的拉力,3 球该匀强电场的场强E图你们 世界上会用流线型下降的鸟是什么 平行板电容器串、并联电压与电源电压各为什么关系?为什么? 我想问矿泉水对人有什么好处? 女性泌尿系统有哪些器官构成 谁知道做害怕意思的shen是哪个字呢? 如题 开姆洛克《220.205》怎么和橡胶粘不牢啊粘住以后很容易就开了粘不牢啊.还有就是6108怎么样啊.金属与胶粘剂粘不牢.铁件上都用砂轮机打磨过. 关于什么EXOmv闹鬼是怎么回事= 看留言说很恐怖所以就特意没看那里,很好奇那个闹鬼的画面是什么?如题 首饰的原料是什么?A、云母B、钻矿C、石英 涂有开姆洛克220的金属与橡胶出现脱离现象是什么造成的吧求求各位大哥大姐们,205做底涂,能举几个实例吗? 请问大家一下在XP中如何计算我写的文章字数 有谁了解的说下吧,感受大伙了劫3 男人硬度问题听同事说她LG刚刚三十六,就经常硬度不够.一开始还行,两分钟后开始软,虽还在里面但是哪种被进攻的感觉一点也不强烈了.男人不到四十真的开始“微软”? 列克纳与开姆洛克有什么区别大面积的金属与橡胶粘结哪种比较合适 谁知道在XP中如何计算我写的文章字数 有谁了解的说下吧, 男,硬度男,23岁,有4,5年的手淫历史,现在那勃起长度有14厘米,但是总是不硬,勃起几分钟之后再无射精情况下就软了,然后经过刺激之后又可以勃起.请问我这是怎么回事,是不是某种病态的开始, 氢氧化钠和氯化铝的问题向a mol NaOH溶液中逐滴加入含b mol AlCl3溶液 若a+b=1,当a取不同值时,生成物可能有如下情况,试回答:(1)全部是氢氧化铝时,a的取值范围是_(2)全部是偏铝酸钠时,a的 请问大家一下在XP中如何计算我写的文章字数 有谁了解的说下吧, 三相同步电动机和三相异步电动机有什么区别?用简单易懂的话解释.能控制转速的是哪种? 氟橡胶跟金属连接用什么胶 用开姆洛克205行不行 还需要添加什么开姆洛克其他型号混合吗? 枭字怎么拼读 酪蛋白与溴甲酚绿指示剂反应的实验目的是什么 为什么我的硬度越来越差了,没有性生活也没有手 淫,有什么办法可改善甚至加强?还有真的有药物能使小弟弟增大增粗吗 倩字的罗马拼音怎么拼写? OP平分∠AOB,PC⊥OA于点C,PD⊥OB于点D,CD与OP交于点Q求证:CQ=DQ 泌尿系统的主要器官 凸透镜使光线折射?凹透镜使光线反射?这两句话对么? OP平分∠AOB,过点P作OP的垂线分别交OA、OB于点C、D 请问:PC=PD吗?为什么?能不能利用角平分线的性质求证呢? 泌尿系统的主要器官是() sheng(shen)得慌怎么写? 请问,对角线元素均为0的对称矩阵,它是半正定的吗?是否是这样的呢:半正定矩阵的对角线元素是非负的,而且零矩阵是一个特殊矩阵。请问对角线元素为0一定能推出是半正定吗? 分辨石头同学们都喜欢小明从乡下带来的漂亮小石头.小明从中取出两块石头说:“这两块石头,一块是高山上的,一块是海边的,谁能最先分辨出来就奖给谁.”同学们,你能分辨出来吗?请说一说 (shen/sen)得慌那个字怎么写? 电子元器件一般含有阻燃剂吗 “.shen"重怎么写 请问大家一下在XP中如何计算我写的文章字数熟悉的看下吧,感受大伙了8e 已知:如图,P是角AOB平分线上的一点,PC垂直于OA,PD垂直于OB,垂足分别为C,D.求证: (1)OC=OD; (2)OP是CD的垂直平分线. 请问下有谁知道在XP中如何计算我写的文章字数 有点着急了啊,打心底麻烦各位 自由电荷从电池正极流出,由负极返回.这句话对吗?自由电荷从电池正极流出,由负极返回.这句话对吗? 什么是原初电荷分离原理? 泌尿系统的主要器官是( 每个( )是由大约100多万个( )组成的?它又是由( ),( ),( )组成. 在闭合的干电池中,电场力电场力如何推动自由电荷充负极向正极运动?这电场力又由什么东西组成的? 为什么电源正负极总保持一定数量的正负电荷.电源没有接入电路时,正负极会保持一定数量的正负电荷吗?我们老师说电路中有电流时,是所有导体和导线中的自由电子定向移动,这样的话正极 谁知道在XP中如何计算我写的文章字数 有谁了解的说下吧,打心底感谢了北4 白云 处有人家,shen是哪个?深还是生?>O 传送带例题在这求几道传送带相关的综合问题(多过程) 有关摩尔根的知识 心电图机英文说明 ECG 8800说明1.PAER SPEED 2.FILER SENSITVITY 3.RESET 4.LEAD 5.SELECTOK 6.START 7.CHECK 以上是 机器上的按钮 英文个位大虾 帮我 韩国“科学技术卫星3”号抵达俄罗斯 500万叙利亚人在国内成难民 冲突严新警方樟宜机场缴7.1公斤冰毒 一外阿富汗总统选举唯一女候选人被取消竞选澳85岁志愿者因慈善工作获得“默多克韩国自主研发太空观测卫星抵俄基地 拟新加坡建房局凭借公共住房项目获得国际阿富汗总统选举唯一女候选人被取消竞选巴西男子计划耗时8个半月穿夹脚拖走遍马副首相为选举造势 出席者可获得小鸡法国数百活动人员斗牛场前集结 抗议斗东京惊现旧日军哑弹 实施爆破超过千人澳大利亚一墓园将举行恐怖派对迎接万圣德外长:美情报机构监听盟国造成巨大政专访:能源领域是中墨合作的良好平台英气象局发高级预警称英或迎来十年最大日本一杂志启用胖模特 专为胖女孩设计加拿大婚外情网站欲进驻新加坡遭民众政世界最高人举行婚礼 与妻子相差77厘英媒:《唐顿庄园》走红被中国人抢注商阿富汗总统选举唯一女候选人被取消竞选彭丽媛陪同丹麦女王参观安徒生童话展男子误陷传销 发微信获解救里皮叹辽足客场困难重重 郑智全力养伤台湾地区国学大师傅佩荣东莞畅谈国学与大风沙尘雨雪霜冻结伴侵甘肃 多地现罕环保法修法严执法应更严《铁证如山 吉林省新发掘日本侵华档案日军奴役劳工档案在吉林省档案馆公布(吉林省档案馆侵华日军南京大屠杀相关档省直机关学习弘扬焦裕禄精神 践行“三张峰出席APEC第49次电信工作组会张东阳因涉嫌严重违纪辞去沈阳检察院检第三届全国民政行业职业技能竞赛暨全国北京城镇居民大病保险报销启动 “二次安倍将于本月29日起访问英法德等欧洲乌防长:俄军距边境1公里 已准备好击乌方:斯拉维扬斯克第二阶段行动目标是爱心人士为独龙族烧伤女童普艳芳筹款大风刮过成都 市民调侃“到单位被吹回一批日本侵华档案公布 南京大屠杀、强“歌剧节“推动中外艺术交流(组图)
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘