Iterator
Iterator
的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6
创造了一种新的遍历命令for...of
循环,Iterator
接口主要供for...of
消费。
每一次调用next
方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value
和done
两个属性的对象。其中,value
属性是当前成员的值,done
属性是一个布尔值,表示遍历是否结束。
1 | var map = new Map([["name", "张三"], ["title", "Author"]]); |
Iterator接口
在ES6
中,有三类数据结构原生具备Iterator
接口:数组、某些类似数组的对象、Set
和Map
结构。
1 | let arr = ['a', 'b', 'c']; |
构造具有Iterator
接口的对象。
1 | class RangeIterator { |
上面的例子是指定对象本身就含有next
函数,所以迭代器函数返回对象本身是可行的。如果要对一个Object
实现迭代功能,则需要对Symbol.Iterator
进行定义。
1 | function Obj(value){ |
上面代码首先在构造函数的原型链上部署Symbol.iterator
方法,调用该方法会返回遍历器对象iterator
,调用该对象的next
方法,在返回一个值的同时,自动将内部指针移到下一个实例。
对于类似数组对象(存在数值键名和length
属性),部署Iterator
接口才会使用扩展运算符和for...of
循环。
1 | var arrayLike = { |
调用Iterator场合
解构赋值
1 | let set = new Set().add('a').add('b').add('c'); |
扩展运算符
1 | // 例一 |
yield*
跟着一个可遍历的结构,会调用该结构的遍历器接口。与function*一起用。
1 | let generator = function* () { |
字符串的Iterator接口
1 | var someString = "hi"; |
Iterator与Generator函数
主要介绍放到下一章节。
1 | var myIterable = {}; |
遍历器对象的return(),throw()
return
方法的使用场合是,如果for...of
循环提前退出(通常是因为出错,或者有break
语句或continue
语句),就会调用return
方法。如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return
方法。
1 | var str = new String("hello world"); |
for…of
一个数据结构只要部署了Symbol.iterator
属性,就被视为具有iterator
接口,就可以用for...of
循环遍历它的成员。也就是说,for...of
循环内部调用的是数据结构的Symbol.iterator
方法。
数组
注意区分的是,for...of
返回的是数组元素,for...in
返回的是数组的键名。
1 | var arr = ['a', 'b', 'c', 'd']; |
另外,for...of
循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。
1 | var arr = [3, 5, 7]; |
Set & Map
1 | var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]); |
类似数组的对象
比如字符串,arguments都可以直接使用for...of
进行遍历。而对于类似数组对象就要使用Array.from
转为数组。
1 | let arrayLike = { length: 2, 0: 'a', 1: 'b' }; |
其他普通对象想要用for...of
遍历,需要使用Object.keys()
。否则只是赋值给iterator接口函数也无法输出。因为它不是一个类数组对象。
另一种方法是使用Generator函数将对象重新包装一下。
1 | var es6 = { |
遍历方法比较
Array.forEach
Array
对象内置有forEach
方法,但是不能中途跳出,break
和return
语句都无法工作。
for…in
循环遍历数组。
数组键名是数组,但是返回会是字符串"0"等等。
不止返回数字键名,还会返回原型链上的键。
循环顺序不稳定。
1 | var arrayLike = { |
总之,for...in
是为遍历对象而设计的,不适合遍历数组。
for…of
1 | for (let value of myArray) { |
有着同for...in一样的简洁语法,但是没有for...in那些缺点。
不同用于forEach方法,它可以与break、continue和return配合使用。
提供了遍历所有数据结构的统一操作接口。