ES6 引入了 Map,Set 等,数据结构越来越多,需要一个统一的接口来处理不同的数据结构,所以引入了迭代器,提供了统一的访问方式:for...of
循环
迭代器 IteratorES6
- 是一个对象,对象里面有
next()
方法 next()
方法返回的结果的格式必须是{ done: Boolean, value: any }
Iterator = {
// ...
next() {
// ...
return {
value: any,
done: Boolean
}
}
}
可迭代对象
是一个特殊的对象:
- 这个特殊的对象要有一个方法:
Symbol.iterator(){}
(for…of 循环启动时,就会调用这个方法) - 方法的返回值是 迭代器(Iterator)(从此开始,for…of 仅作用于这个被返回的对象)
iterableObj = {
// ...
[Symbol.iterator]() {
return { // return Iterator
// ...
next() {
// ...
return {
value: any,
done: Boolean
}
}
}
}
}
可迭代
只要满足上面可迭代对象的条件就是可迭代的,有以下作用:
- 可以被
for...of
循环遍历 - 可用于
展开语法
- 解构赋值
yield*
Array.from()
Promise.all()
Promise.race()
内置的可迭代对象
String
Array
Map
Set
- 函数的
arguments
对象 NodeList
TypedArray
FormData
URLSearchParams
此时可以通过 for...of
循环遍历元素(解决了 for...in
遍历对象的“属性”问题以及 Set,Map 等的遍历问题)
数据转换
用途
将一个普通对象改成可迭代对象:
let range = {
from: 1,
to: 5,
[Symbol.iterator]() { // 在 for..of 循环开始时被调用一次
return {
current: this.from,
last: this.to,
next() { // 每次迭代时都会被调用,来获取下一个值
if (this.current <= this.last) {
return { done: false, value: this.current++ }
} else {
return { done: true }
}
}
};
}
}
for(let value of range) {
console.log(value); // 1,然后 2,然后 3,然后 4,然后 5
}
异步可迭代对象
与上面类似,但是可以异步地每秒返回一个值:
let range = {
from: 1,
to: 5,
[Symbol.asyncIterator]() { // (1)
return {
current: this.from,
last: this.to,
async next() { // (2)
// 注意:我们可以在 async next 内部使用 "await"
await new Promise(resolve => setTimeout(resolve, 1000)) // (3)
if (this.current <= this.last) {
return { done: false, value: this.current++ }
} else {
return { done: true }
}
}
};
}
};
(async () => {
for await (let value of range) { // (4)
console.log(value); // 1,2,3,4,5
}
})()
(1)使用 Symbol.asyncIterator
(2)next()
返回一个 promise
(3)next()
可以不是 async 函数,但是里面使用 await 更方便
(4)使用 for await...of
进行迭代
Warning
需要常规的同步 iterator 的功能,无法与异步 iterator 一起使用
例如,spread 语法无法工作:alert( [...range] ); // Error, no Symbol.iterator
Iterator 和异步 iterator 之间差异
Iterator | 异步 iterator | |
---|---|---|
提供 iterator 的对象方法 | Symbol.iterator | Symbol.asyncIterator |
next() 返回值 | 任意值 | Promise |
要进行循环,使用 | for...of | for await...of |
NOTE
for...of
会寻找同步 Iterator,for await...of
会寻找异步 Iterator。可以在一个对象中同时添加同步和异步的 Iterator,拥有 2 种迭代方式,但是这样会比较奇怪
Warning
同步 Iterator 地 next 如果返回了一个 Promise,那么
for...of
将无限循环。因为 Promise 对象不是期望的格式,for…of 循环无法正确处理它,并且认为迭代尚未完成