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
+ ?