js之Iterator和for...of循环


Iterator概念

js表示集合的数据结构,主要有Array,Object,Map和Set,为了统一接口机制,来处理这四种不同的数据结构,所以就有Iterator。
Iterator创建了新的遍历命令for…of循环。

Iterator遍历过程

创建一个指针指向首个成员,按照次序使用next()指向下一个成员,直接到结束位置。
每次调用next方法,返回当前成员的信息。用{value: , done: }对象表示,done表示是否结束,默认为false,结束是true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 模拟next方法
var it = makeIterator(['a', 'b']);

it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }

function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{value: undefined, done: true};
}
};
}

对于遍历器对象来说,done:false和value:undefined可以省略,所以可以简写成

1
2
3
4
5
6
7
8
9
10
11
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++]} :
{done: true};
}
};
}
`

几种遍历方式比较

for of 循环不仅支持数组、大多数伪数组对象,也支持字符串遍历,此外还支持 Map 和 Set 对象遍历。
for in循环可以遍历字符串、对象、数组,不能遍历Set/Map
forEach 循环不能遍历字符串、对象,可以遍历Set/Map

哪些数据结构可以用for…of

ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。

原生具备Iterator接口数据结构的类型

不具备Iterator接口:Object
具备Iterator接口:
Array/Map/Set/String/TypedArray/函数的 arguments 对象/NodeList 对象

1
2
3
4
// 如何确定是否有Iterator接口
Object.getOwnPropertySymbols(Array.prototype) // [Symbol(Symbol.iterator), Symbol(Symbol.unscopables)]
Object.getOwnPropertySymbols(String.prototype) // [Symbol(Symbol.iterator)]
Object.getOwnPropertySymbols(Object.prototype) // []

(未完)