ES6 Iterator迭代器 與 Generator生成器 如何用js封裝一個遍歷所有可迭代資料結構的方法
阿新 • • 發佈:2022-04-11
ES6 Iterator迭代器 與 Generator生成器
1.1 為什麼要有 Iterator
在ES6語法中,有序資料結構已有許多
如Array、Set、Map、String、類陣列(如arguments)等
當我們不確定資料是何種型別但又要對它進行遍歷時,我們只能去做針對性的判斷處理
因此,一個統一的介面來遍歷所有資料型別是很有必要的,而Iterator扮演了這一角色
1.2 什麼是Iterator
- 具有[Symbol.iterator]屬性,且屬性值是function型別
- 執行此function返回一個迭代器物件,此物件有next方法可順序迭代子元素
- forof可遍歷此迭代器
在js中,實現了Iterator介面的資料結構都是可迭代的
具體表現為資料結構的[Symbol.iterator]屬性值是function型別
const isIterable = target => typeof target?.[Symbol.iterator] === 'function'
當迭代器順序執行完畢之後,後續執行返回的done為true,作為迭代結束的標誌
function arrLike(){ const it = arguments[Symbol.iterator]() console.log(it) // Object [Array Iterator] {} console.log(it.next()) // { value: 1, done: false } console.log(it.next()) // { value: 2, done: false } console.log(it.next()) // { value: 3, done: false } console.log(it.next()) // { value: undefined, done: true } } arrLike(1,2,3)
封裝一個迭代函式,用於遍歷js中所有可迭代的資料結構
// 判斷是否可迭代 const isIterable = target => typeof target?.[Symbol.iterator] === 'function' function each(target,callback){ if(!isIterable(target)){ throw 'the first parameter must be iterable(need a [Symbol.iterator] property)' } typeof callback !== 'function' && (callback = console.log) const iterator = target[Symbol.iterator]() // 或者用forof // for (const item of iterator) { // callback(item) // } let item = {done:false} while(!item.done){ item = iterator.next() !item.done && callback(item.value) } } each([2,3,4],console.log) each('abc',console.log)
2 Generator生成器與迭代器
一個生成器函式必定返回一個生成器物件,並且這個物件符合迭代器協議
因此這個生成器物件可以被forof遍歷,同樣的具有next方法
function* testGen(){}
console.log(testGen()) // Object [Generator] {}
function* helloWorldGenerator(){
yield 'hello'
yield 'world'
yield 'generator'
return 'end'
}
const genIterator = helloWorldGenerator()
console.log(genIterator.next()) // { value: 'hello', done: false }
each(genIterator,console.log)