概念
遍历器(Iterator
)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator
接口,就可以完成遍历操作。
作用:
- 为各种数据结构,提供一个统一的、简便的访问接口;
- 使得数据结构的成员能够按某种次序排列;
for...of
依靠的就是Iterator
实现的。
基本使用
function makeIterator(arr){
let nextIndex = 0;
return {
next: function(){
return nextIndex < arr.length?
{ value: arr[nextIndex++], done: false }:
{ value: undefined, done: true};
}
}
}
let it = makeIterator(['a', 'b', 'c']);
it.next(); // {value: "a", done: false}
it.next(); // {value: "b", done: false}
it.next(); // {value: undefined, done: true}
定义一个函数,返回一个next
方法,这个方法返回包含了value
和done
的对象,其中done
代表循环是否到了头。
常见的可迭代的数据结构
Array、Map、Set、String、TypeArray、arguments和NodeList
都具备Iterator
接口,所以可以使用for...of
循环它们。
以数组为例:
const arr = [1, 2];
console.log(arr); // 在arr.__proto__中存在Symbol.iterator
let it = arr[Symbol.iterator]();
console.log(it.next()); // {value: 1, done: false}
console.log(it.next()); // {value: 2, done: false}
console.log(it.next()); // {value: undefined, done: true}
for(let i of arr){
console.log(arr);
}
// 1
// 2
默认调用了Iterator
的场景:
- 解构赋值;
- 扩展运算符;
yield*
;for...of
;Array.from()
;Map(), Set(), WeakMap(), WeakSet()
;Promise.all()
;Promise.race()
。
实际应用
假定有这么一个对象:
let obj = {
'All': '不限',
0: '按男生搜索',
1: '按女生搜索'
}
由于对象不能使用for.. of
循环,我们使用for..in
循环:
for(let key in obj){
console.log(key);
}
// 打印的顺序是 0 1 All
这时候有一个需要求,是需要先显示All
,再显示其他选项, 所以可以给obj
新增iterator
,使得数据结构的成员能够按某种顺序排列:
// 获得当前的对象的所有key,并按一定顺序存入数组中,每次next时就返回数组对应的key
function makeIterator(){
const self = this;
let keys = Object.keys(this);
let arr = [];
keys.forEach(key => {
if(key === 'All'){
arr.unshift(key);
}else {
arr.push(key);
}
});
let len = arr.length;
let nextIndex = 0;
return {
next(){
return nextIndex < len?
{ value: arr[nextIndex++], done: false }:
{ value: undefined, done: true};
}
}
}
let obj = {
0: '按男生搜索',
1: '按女生搜索',
'All': '不限',
[Symbol.iterator]: makeIterator
}
for(let k of obj){
console.log(k); // All 0 1
}
这样即为对象提供了for...of
方法,也能按照自己想要的迭代顺序迭代了。
参考
若有错误,欢迎指出,感谢~