以下內容整理自這段影片 Iterators in JavaScript using Quokka
什麼是 iterators ?
為什麼 for…of 可以對 Array 做迭代 ?
Array 提供了
iterators給for...ofloop,讓for...ofloop 利用 iterators 進行迭代。
那 for…of 又是怎麼得到 iterators ?
要解釋這個,要先岔開說一下 Symbol。
Symbol 是什麼? 影片中解釋它可以看作是一個 unique key。至於詳細的 Symbol.iterator 說明可以參考 MDN Symbol。
下面例子裡面的變數 iterator 會回傳一個物件,並且帶有 next 屬性可以執行。這和 generator* 有關,之後會再發一篇有關 generator 說明。
就是因為 iterator 的這個特性,所以和 forEach 不同, for...of 可以對除了 Array 以外的東西進行迭代,String 也可以。只要進行迭代的對象具有 iterator 屬性就可以。
用以下的例子來做說明:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const dragons = [
'cool dragon',
'angry dragon',
'nasty dragon'
]
Symbol.iterator // Symbol{}
const iterator = dragons[Symbol.iterator]()
iterator // {[Iterator]}
// 下面這段就是 for...of loop 在執行的
iterator.next() // 會得到物件:{value: 'cool dragon', done: false}
iterator.next() // 會得到物件:{value: 'angry dragon', done: false}
iterator.next() // 會得到物件:{value: 'nasty dragon', done: false}
iterator.next() // 會得到物件:{value: 'undefined', done: true}
for(const dragon of dragons){
}
1 | // 引入 randomNumber |
下面這個例子就是直接自己寫一個 for…of 的效果
Symbol.iterator會回傳一個 object,裡面有 next 屬性。- 和上面的例子做對照,可以看得比較清楚 iterator 到底是怎麼操作執行的。
- 真正的 iterator 不會設定一個隨機變數去控制執行的次數。這裡只是說明可以自己設定 iterator 執行的條件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const dragonArmy = {
[Symbol.iterator]: () => {
return {
next: () => {
const enoughDragonSpawned = Math.random() > 0.75;
if(!enoughDragonSpawned)
return {
value: makeDragon(),
done: false
}
return {done: true}
}
}
}
}
for (const dragon of dragonArmy){
dragon //
}
小結
- 可以自己建立想要的 iterators 進行迭代。
- iterators 也可以是 Asynchronous。
generator之後會再另外提到,它是一個建立 iterators 的語法糖。
參考資料
Iterators in JavaScript using Quokka
很喜歡這個 Youtube 頻道,推薦大家沒事可以看看。