一、什么是Iterator接口
Iterator
是帶有特殊接口的對象。含有一個 next()
方法偏序,調(diào)用返回一個包含兩個屬性的對象续膳,分別是value
和done
改艇,value
表示當(dāng)前位置的值,done
表示是否迭代完坟岔,當(dāng)為true的時候谒兄,調(diào)用next
就無效了。
在ES5
中遍歷通常用for
循環(huán)社付,數(shù)組還有 forEach
方法承疲,對象就是 for-in
,ES6 中又添加了 Map
和 Set
鸥咖,而迭代器可以統(tǒng)一處理所有集合數(shù)據(jù)的方法燕鸽。迭代器是一個接口,只要你這個數(shù)據(jù)結(jié)構(gòu)暴露了一個iterator
的接口啼辣,那就可以完成迭代啊研。ES6
創(chuàng)造了一種新的遍歷命令for...of
循環(huán),Iterator
接口主要供for...of
消費鸥拧。
數(shù)據(jù)結(jié)構(gòu)只要部署了Iterator
接口党远,我們就認(rèn)為這種數(shù)據(jù)結(jié)構(gòu)為“可遍歷”(Iterable
)。ES6
規(guī)定富弦,默認(rèn)的 Iterator
接口部署在數(shù)據(jù)結(jié)構(gòu)的 Symbol.iterator
屬性沟娱,或者說,一個數(shù)據(jù)結(jié)構(gòu)只要具有 Symbol.iterator
數(shù)據(jù)腕柜,就可以認(rèn)為是“可遍歷的”(iterable
)济似。
可以供 for...of 消費的原生數(shù)據(jù)結(jié)構(gòu)
- Array
- Map
- Set
- String
- TypedArray(一種通用的固定長度緩沖區(qū)類型,允許讀取緩沖區(qū)中的二進制數(shù)據(jù))函數(shù)中的 arguments 對象
- NodeList 對象
可以發(fā)現(xiàn)上面的原生數(shù)據(jù)結(jié)構(gòu)中沒有對象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}
}
這里直接調(diào)用數(shù)組的Symbol.iterator
接口盏缤,這個接口其實是數(shù)組內(nèi)部已經(jīng)幫我們實現(xiàn)了砰蠢,所以我們可以直接調(diào)用,返回的是一個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 //是否結(jié)束 false還沒有結(jié)束
}
} else {
return {
value: arr[index++],
done: true //是否結(jié)束 true已經(jīng)結(jié)束
}
}
}
}
}
};
for (let key of obj) {
console.log(key)
}
}