迭代器
迭代器是被設(shè)計專用于迭代的對象,帶有特定接口关噪。所有的迭代器對象都擁有next()方法拿穴,會返回一個結(jié)果對象。該結(jié)果對象有兩個屬性:對應(yīng)下一個值的value,以及一個布爾類型的done秀仲,其值為true時表示沒有更多值可供使用融痛。迭代器持有一個指向集合位置的內(nèi)部指針,每當(dāng)調(diào)用了next()方法神僵,迭代器就會返回相應(yīng)的下一個值雁刷。
使用es5模擬一個迭代器
function createIterator(items) {
var i = 0
// 返回一個迭代器對象
return {
next: () => {
var done = i >= items.length
var value = !done ? items[++i] : undefined
return {
done,
value
}
}
}
}
var list = createIterator([1, 2, 3, 4, 5])
console.log(list.next()) // { done: false, value: 2 }
console.log(list.next()) // { done: false, value: 3 }
console.log(list.next()) // { done: false, value: 4 }
console.log(list.next()) // { done: false, value: 5 }
console.log(list.next()) // { done: true, value: undefined }
生成器
生成器(generator)是能返回一個迭代器的函數(shù)。生成器函數(shù)由放在function關(guān)鍵字之后的一個星號(*)來表示保礼,并能使用新的yield關(guān)鍵字沛励。將星號緊跟在function關(guān)鍵字之后,或是在中間留出空格炮障,都是沒問題的侯勉。
function *createIterator() {
yield 1
yield 2
yield 3
}
let iterator = createIterator()
console.log(iterator.next().value) // 1
console.log(iterator.next().value) // 2
console.log(iterator.next().value) // 3
可迭代對象與 for-of 循環(huán)
與迭代器緊密相關(guān)的是,可迭代對象(iterable)是包含Symbol.iterator屬性的對象铝阐。這個Symbol.iterator知名符號定義了為指定對象返回迭代器的函數(shù)址貌。在 ES6 中,所有的集合對象(數(shù)組徘键、 Set 與 Map )以及字符串都是可迭代對象练对,因此它們都被指定了默認(rèn)的迭代器。
for-of循環(huán)在循環(huán)每次執(zhí)行時會調(diào)用可迭代對象的next()方法吹害,并將結(jié)果對象的value值存儲在一個變量上螟凭。循環(huán)過程會持續(xù)到結(jié)果對象的done屬性變成true為止。
let value = [1, 2, 3]
for (let num of value) {
console.log(num)
}
輸出:
1
2
3
訪問默認(rèn)迭代器 Symbol.iterator
let values = [1, 2, 3, 4, 5]
let iterator = values[Symbol.iterator]()
iterator.next() // {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: false}
集合的迭代器
ES6 具有三種集合對象類型:數(shù)組它呀、 Map 與 Set 螺男。
- entries():返回一個包含鍵值對的迭代器;
- values():返回一個包含集合中的值的迭代器纵穿;
- keys():返回一個包含集合中的鍵的迭代器下隧。
let map = new Map([['name', 'age'], ['map', 5]])
map.entries() // MapIterator {"name" => "age", "iterator" => 5, "friends" => "none"}
map.values() // MapIterator {"map", 5}
map.keys() // MapIterator {"name", "age"}
let set = new Set([1, 2, 3, 4, 5])
set.entries() // SetIterator {1 => 1, 2 => 2, 3 => 3}
set.values() // SetIterator {1, 2, 3, 4, 5}
set.keys() // SetIterator {1, 2, 3, 4, 5}
let arr = [1, 2, 3, 4, 5]
arr.entries() // Array Iterator {}
arr.values() // Array Iterator {}
arr.keys() // Array Iterator {}
調(diào)用迭代器方法返回的數(shù)據(jù)需要通過 for...of... 來遍歷
字符串的迭代器
從 ES5 發(fā)布開始, JS 的字符串就慢慢變得越來越像數(shù)組谓媒。例如 ES5 標(biāo)準(zhǔn)化了字符串的方括號表示法淆院,用于訪問其中的字符(即:使用text[0]來獲取第一個字符,以此類推)句惯。
所以也可以像遍歷集合那樣遍歷字符串
- 傳統(tǒng) for 循環(huán)
- for...of...
NodeList 的迭代器
文檔對象模型( DOM )具有一種NodeList類型土辩,用于表示頁面文檔中元素的集合。NodeList對象與數(shù)組都使用了length屬性來標(biāo)明項的數(shù)量抢野,并且都使用方括號表示法來訪問各個項拷淘。然而本質(zhì)上來說,NodeList與數(shù)組的行為是完全不同的指孤,這會引發(fā)許多混亂启涯。
著默認(rèn)迭代器被附加到 ES6 , DOM 關(guān)于NodeList的規(guī)定也包含了一個默認(rèn)迭代器(此規(guī)定在 HTML 規(guī)范而非 ES6 規(guī)范中),其表現(xiàn)方式與數(shù)組的默認(rèn)迭代器一致逝嚎。這意味著你可以將NodeList用于for-of循環(huán)扁瓢,或用于其他使用對象默認(rèn)迭代器的場合。
let divs = document.getElementsByTagName("div")
for (let div of divs) {
console.log(div.id)
}