一、什么是Iterator接口
Iterator
是带有特殊接口的对象。含有一个 next()
方法,调用返回一个包含两个属性的对象,分别是value
和done
,value
表示当前位置的值,done
表示是否迭代完,当为true的时候,调用next
就无效了。
在ES5
中遍历通常用for
循环,数组还有 forEach
方法,对象就是 for-in
,ES6 中又添加了 Map
和 Set
,而迭代器可以统一处理所有集合数据的方法。迭代器是一个接口,只要你这个数据结构暴露了一个iterator
的接口,那就可以完成迭代。ES6
创造了一种新的遍历命令for...of
循环,Iterator
接口主要供for...of
消费。
数据结构只要部署了Iterator
接口,我们就认为这种数据结构为“可遍历”(Iterable
)。ES6
规定,默认的 Iterator
接口部署在数据结构的 Symbol.iterator
属性,或者说,一个数据结构只要具有 Symbol.iterator
数据,就可以认为是“可遍历的”(iterable
)。
可以供 for...of 消费的原生数据结构
- Array
- Map
- Set
- String
- TypedArray(一种通用的固定长度缓冲区类型,允许读取缓冲区中的二进制数据)函数中的 arguments 对象
- NodeList 对象
可以发现上面的原生数据结构中没有对象Object
{
let arr = ['hello', 'world'];
let map = arr[Symbol.iterator]();
console.log(map.next());// {value: "hello", done: false}
console.log(map.next());// {value: "world", done: false}
console.log(map.next());// {value: undefined, done: true}
}
这里直接调用数组的Symbol.iterator
接口,这个接口其实是数组内部已经帮我们实现了,所以我们可以直接调用,返回的是一个map
,map
有一个next
方法
对象Object是没有Iterator
接口的,无法通过for...of
的方式遍历对象
{
let obj = {
start: [1, 3, 5],
end: [2, 4, 6],
};
// Object 没有 Iterator接口
// 会报错obj[Symbol.iterator] is not a function
// for (let key of obj) {
// console.log(key);
// }
}
那是否可以自定义一个Iterator接口呢?答案是可以的
{
let obj = {
start: [1, 3, 5],
end: [2, 4, 6],
[Symbol.iterator]() {
let self = this;
let index = 0;
let arr = self.start.concat(self.end);
let len = arr.length;
return {
next() {
if (index < len) {
return {
value: arr[index++],
done: false //是否结束 false还没有结束
}
} else {
return {
value: arr[index++],
done: true //是否结束 true已经结束
}
}
}
}
}
};
for (let key of obj) {
console.log(key)
}
}
网友评论