什么是遍历器
Iterator
是一种接口,为各种不同的数据结构提供统一的访问机制(即 for...of
循环)。任何数据结构只要部署 Iterator
接口,就可以完成遍历操作。
- 为各种数据结构(
Array
,Object
,Map
,Set
等),提供一个统一的、简便的访问接口 - 使得数据结构的成员能够按某种次序排列
ES6
创造了一种新的遍历命令for...of
循环,Iterator
接口主要供for...of
消费
Iterator 的遍历过程
- 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
- 第一次调用指针对象的
next
方法,可以将指针指向数据结构的第一个成员。 - 第二次调用指针对象的
next
方法,指针就指向数据结构的第二个成员。 - 不断调用指针对象的
next
方法,直到它指向数据结构的结束位置。
简单的迭代器示例
const it = makeIterator(['a', 'b'])
console.log(it.next())
console.log(it.next())
console.log(it.next())
function makeIterator (array) {
var nextIndex = 0
return {
next: function () {
return nextIndex < array.length ?
{ value: array[nextIndex++], done: false } :
{ value: undefined, done: true }
}
}
}
哪些数据结构支持 iterator
Array
Map
Set
String
TypedArray
- 函数的
arguments
对象 NodeList
对象
以上数据结构进行 for...of
循环时,该循环会自动去寻找 Iterator
接口。
没有 Iterator
接口的要如何遍历
比如对象(Object
)默认是没有 Iterator
接口,那么它就不能被 for...of
遍历
如下所示,for...of
对 Object
遍历,会提示 obj is not iterable
,它不是一个遍历器
const obj = { name: 'wfly', age: '18' }
for (item of obj) {
console.log(item);
}
要想不支持 Iterator
接口的,实现 for...of
循环,需要在此数据类型上部署 Iterator
接口,如下
const obj = {
name: 'wfly', age: '18',
[Symbol.iterator]: function () {
var nextIndex = 0
return {
next: function () {
return nextIndex < 3 ?
{ value: nextIndex++, done: false } :
{ value: undefined, done: true }
}
}
}
}
for (item of obj) {
console.log(item);
}
所以只要是部署了
Iterator
接口数据结构,那么它就是可被for...of
循环遍历的
为什么对象这种数据结构没有部署遍历器接口
- 对象的哪个属性先遍历,哪个属性后遍历是不确定的,因为对象是无序的
- 遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换
- 对象部署遍历器接口并不是很必要,
ES6
提供了Map
数据结构可供for...of
遍历循环
调用遍历器接口的场景
解构赋值
对数组和 Set
结构进行解构赋值时,会默认调用 Symbol.iterator
方法。
let set = new Set().add('a').add('b').add('c');
let [x,y] = set;
// x='a'; y='b'
let [first, ...rest] = set;
// first='a'; rest=['b','c'];
扩展运算符
扩展运算符(…)也会调用默认的 Iterator
接口。
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']
所以只要某个数据结构部署了
Iterator
接口,就可以对它使用扩展运算符,将其转为数组。
字符串的 Iterator 接口
字符串是一个类似数组的对象,也原生具有 Iterator
接口。
如下所示
var a = '1231231'
for (item of a) {
console.log(item);
}
其他场合
yield*
for...of
Array.from()
Map(), Set(), WeakMap(), WeakSet()
Promise.all()
Promise.race()