本文雲紋連接🔗javascript
專門說一說Iterator
迭代器的緣由是,爲後面async/await
的文章作鋪墊,由於我async/await
是由Generator
+Promise
共同構成,而其中的Generator
就是依賴於迭代器Iterator
。java
下面讓咱們來看看什麼是Iterator
?它出現的目的是什麼?如何使用它?es6
Iterator
迭代器名詞: 迭代 iteration / 可迭代 iterable / 迭代器 iterator
想必你們使用過for循環、while循環等,遍歷Array獲取其中的值,那其餘數據結構如何經過遍歷獲取呢?或者這樣說,是否能夠提供一個統一的訪問機制?來訪問Object、Map、Set等。編程
輪到Iterator
迭代器出場,Iterator
迭代器就是爲了解決這個問題,它提供統一的接口,爲不一樣的數據結構提供統一的訪問機制。(目前Map、Set、Array支持Iterator
)。segmentfault
顧名思義,Iterator
迭代器的出現就是爲了迭代而生,爲不一樣的集合:Object、Array、Map、Set,提供了一個統一的接口(這裏接口能夠簡單的理解爲方法,就是遍歷方法)。向咱們經常使用的for...of
就是依賴與Iterator
迭代器。數組
在這裏順便提一嘴,我理解到的遍歷、迭代的關係:遍歷就是訪問數據結構的全部元素,而迭代是遍歷的一種形式。數據結構
// 阮一峯 ECMAScript 6 入門 // 模擬next方法返回值 var it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true } function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true} } } }
上面的makeIterator
函數,它就是一個迭代器生成函數
,做用就是返回一個迭代器對象。對數組執行這個函數,就會返回該數組的迭代器對象it。異步
經過調用next
函數,返回value
和done
兩個屬性;value屬性返回當前位置的成員,done屬性是一個布爾值,表示遍歷是否結束,便是否還有必要再一次調用next方法;當done
爲true時,即遍歷完成。async
小結:Iterator
迭代器就是一個接口方法,它爲不一樣的數據結構提供了一個統一的訪問機制;使得數據結構的成員可以按某種次序排列,並逐個被訪問。異步編程
Iterator
規範在上面的代碼中,迭代器對象it
包含一個next()
方法,調用next()
方法,返回兩個屬性:布爾值done
和值value
,value的類型無限制。
迭代器對象包含的屬性咱們知道了,那麼在平常開發中,咱們如何讓一個對象成爲一個可迭代對象
呢?(可迭代對象即支持迭代器規範的對象)
要成爲可迭代對象, 一個對象必須實現@@iterator
方法。這意味着對象(或者它原型鏈上的某個對象)必須有一個鍵爲@@iterator
的屬性,可經過常量 Symbol.iterator
訪問該屬性。
let myIterable = { a: 1, b: 2, c: 3 } myIterable[Symbol.iterator] = function() { let self = this; let arr = Object.keys(self); let index = 0; return { next() { return index < arr.length ? {value: self[arr[index++]], done: false} : {value: undefined, done: true}; } } } var it = myIterable[Symbol.iterator](); it.next(); for(const i of myIterable) { console.log(i); }
將myIterable
對象添加Symbol.iterator
屬性,同時在返回的next
方法中,添加兩個屬性,既讓它成爲了一個可迭代對象。(其實若是真的有這樣的需求,能夠考慮使用Map
)。
小結:Iterator
規範————Iterator
迭代器包含一個next()
方法,方法調用返回返回兩個屬性:done
和value
;經過定義一個對象的Symbol.iterator
屬性,便可將此對象修改成迭代器對象
,支持for...of
遍歷。
Iterator
和Generator
Generator
和Promise
同樣,都是提供異步編程解決方案。其實Generator函數就是一個普通函數,可是有兩個特徵,一是,function關鍵字與函數名之間有一個星號*;二是,函數內部使用yield表達式,定義不一樣的內部狀態。來看看Generator函數的使用:
function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenerator(); hw.next() // { value: 'hello', done: false } hw.next() // { value: 'world', done: false } hw.next() // { value: 'ending', done: true } hw.next() // { value: undefined, done: true }
經過上面的例子能夠知道,Generator
函數執行後,會返回一個Iterator
對象。在Generator
中的yield表達式,yield會記住當前代碼運行的狀態和位置,等在調用這串代碼的時候會依次日後走。
Iterator
(迭代器)就是一個可迭代的對象,而Generator
(生成器)使用了yield或者生成器表達式,生成iterator對象,用一種方便的方法實現了iterator,在for循環取數據或使用next()取數據.
小結:Generator
(生成器)能夠理解爲是對Iterator
(迭代器)的一種實現。
Iterator
應用Generator
(生成器)就是其中最典型的一個應用,固然還有其餘,例如:Map、Set、Array等原生具有Iterator
(迭代器),支持for...of
循環。
Iterator
接口Object對象雖然不支持Iterator
(迭代器),但咱們可使用Generator
(生成器)進行包裝。
let obj = {a: 1, b: 2, c: 3} function* entries(obj) { for (let key of Object.keys(obj)) { yield [key, obj[key]]; } } for (let [key, value] of entries(obj)) { console.log(key, '->', value); }
目前在Array、Map、Set、String、TypedArray、函數的 arguments 對象、NodeList 對象
,原生具有Iterator
接口。
參考: