Iterators 与 for-of 循环
Iterators 与 for-of 循环
循环遍历数组的几种方式
for循环
1 | var myArray = [1, 2, 3] |
ES5 forEach
1 | var myArray = [1, 2, 3] |
forEach的内部函数无法使用 break 或 return(?)
for-in
1 | var myArray = [1, 2, 3] |
用for–in循环遍历数组不可取:
index是字符串而不是数字:
"0","1","2"等有时候不以正常的顺序循环遍历
无法正常遍历某些数组, 如:
1 | var a = [] |
1 | var a = [] |
- 数组中若有可枚举属性(enumerable property)?,也会被遍历
1 | Array.prototype.foo = 1 |
for-of
- 遍历数组最简单直接的方式
- 没有
for-in,forEach存在的那些缺陷 与
for-in的区别:for-in循环遍历对象属性for–of循环遍历数据(如数组中的各个元素)for-of还可以循环遍历其它类型的集合, 如类数组对象: NodeLists, 字符串等:
1 | for (var chr of "😺😲") { |
- 也可以用于遍历
Set和Map对象:
1 | var words = ['a', 'b', 'c'] |
对于Map对象, 需要先解构再遍历:
1 | for (var [key, value] of phoneBookMap) { |
- 不过
for-of不可直接用于遍历一般的对象(plain object), 如果想要遍历这种对象的属性, 应该借助for-in或者Object.keys():
1 | var someObject = { 0: 'a', 1: 'b', 2: 'c', 'hello': 'world' }; |
for-of的原理
for-of通过调用对象方法起作用, Array, Map, Set等可遍历的对象都有个共同特点, 它们有遍历器(iterator)方法.
for-of无法遍历一般的对象是因为一般对象的属性中没有遍历器方法, 不过我们可以手动在对象原型中添加该方法myObject[Symbol.iterator](), 就能够使该对象可以被for-of循环遍历:
使用for–of循环遍历对象, 首先调用了[Symbol.iterator]()方法, 调用后的结果是返回一个新的可遍历的对象, 这个对象的属性中有个next()方法, for-of在每一次循环中都会调用一次该方法. 以下是一个简单的可遍历对象的例子:
1 | var zeroesForeverIterator = { |
对于以上的对象, 每次next()被调用, 都会返回同样的结果, 告诉for-of循环: 1).遍历还未结束; 2). 下一个值是0.
此时,for (value of zeroesForeverIterator) {}就是个无限循环.
含有遍历器方法的对象还实现了可选的.return()方法和.throw(exc)方法. 如果循环由于抛出异常或break或return声明过早退出, for-of会调用.return(). 不过大部分情况下, 不需要用到.return()方法, .throw(exc)更特殊, for-of从不调用该方法. (more about it?)
1 | for (VAR of ITERABLE) { |
以上for-of循环, 实际上执行的操作是(简单版本):
1 | var $iterator = ITERABLE[Symbol.iterator](); |
以上只是简单的版本, 大致体现了for-of是如何实现的, 实际上更复杂, 但对于理解上并没有太大的帮助, 因此省略某些方法的实现(例如是如何处理return()的). for-of很好用, 但是底层的实现比较复杂.
使用for-of
截至原文完成的时间(2015-04-29), 某些浏览器还不支持for-of, 在Chrome中, 可打开chrome://flags找到“Experimental JavaScript”并进行启用. 在服务端想要使用该特性, 在执行Node指令时加上--harmony选项.
Resources
Next articles will be:
CSS Modules
Questions In This Article: cmd + f + ?