ES6 的遍歷器接口 Iterator

1、概念

遍歷器(Iterator)是一種接口,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構只要部署Iterator接口,就能夠完成遍歷操做(即依次處理該數據結構的全部成員)。es6

Iterator的做用有三個:一是爲各類數據結構,提供一個統一的、簡便的訪問接口;二是使得數據結構的成員可以按某種次序排列;三是ES6有一種新的遍歷方式,for...of,而Iterator的主要做用,就是支持此操做。數組

 

2、是否具有遍歷器(Iterator)接口

在ES6中,有些數據結構原生具有Iterator接口(好比數組),即不用任何處理,就能夠被for...of循環遍歷,有些就不行(好比對象)。緣由在於,這些數據結構原生部署了Symbol.iterator屬性(詳見下文),另一些數據結構沒有。數據結構

凡是部署了Symbol.iterator屬性的數據結構,就稱爲部署了遍歷器接口。調用這個接口,就會返回一個遍歷器對象。函數

在ES6中,有三類數據結構原生具有Iterator接口:數組、某些相似數組的對象、Set和Map結構。它們三者不須要咱們手動部署Symbol.iterator屬性就能夠使用for...of遍歷功能。而普通對象使用for...of遍歷就會報錯,由於它沒有部署該接口。spa

 

3、部署接口

若是你須要使本來不具有for...of遍歷功能的集合具有該功能,就須要手動爲它部署。ES6有許多內置的Symbol值,這些就是接口。prototype

下面咱們利用迭代器中的原理來給對象生成一個迭代器,實現讓對象能夠使用for...ofcode

 

var person={ name: 'zz', age: 18 }
//給person對象添加一個iterator接口 person[Symbol.iterator] = function(){
//使用object.keys()方法把j對象中的k值讀取出來存在數組當中 var arr = Object.keys(person); var i = 0; return { //ES6中next()迭代方法,自動迭代 next(){ if(i < arr.length){ //若是done爲false,繼續迭代 return { //返回迭代的最後結果,若是是一個對象,那麼for of的時候須要用解構 value: { k : arr[i], val: person[arr[i++]] }, done: false } }else{ //若是done爲true,繼續迭代 return { value: null, done : true } } } } }
//解構獲取返回獲得的對象,輸出k值,val值 for(var {key,val} of person){ console.log(key,val); }

 

 

咱們能夠看到:對象

一、經過爲person對象部署Symbol.iterator接口,就使它實現了for...of 功能。blog

二、Symbol.iterator中返回一個對象,該對象包含一個next() 方法,定義了遍歷功能。接口

三、next方法中的value和done,value是遍歷過程當中返回的鍵值對信息,done是一個表示遍歷是否結束的布爾值。

 

補充:

一、遍歷器對象除了具備next方法,還能夠具備return方法和throw方法。若是你本身寫遍歷器對象生成函數,那麼next方法是必須部署的,return方法和throw方法是否部署是可選的。

  當一個解構在遍歷的時候異常提早退出(好比break,continue或者出錯)的時候,就會調用return方法,其次,return方法必須返回一個對象。

  至於throw方法,則是用於拋出錯誤,Generator.prototype.throw這裏不展開講了,感興趣的能夠搜索一下。

 

二、用ES6新功能Generator函數來實現Symbol.iterator接口,事半功倍。

var yieldIterator = {}; yieldIterator[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; }; [...yieldIterator] // [1, 2, 3]

注意,yield* 後面跟的是一個可遍歷的結構,它會調用該結構的遍歷器接口。

對Generator不瞭解的能夠戳 ES6 Generator的語法 ,這裏很少說。

 

三、至於能夠使用Array.from轉換成數組的類數組對象,部署iterator有一種很簡單的方法,即直接使用數組的[Symbol.iterator]接口。

fakeArray.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

 

4、默認調用Iterator接口的場景

一、解構賦值

二、擴展運算符(...)

三、上文提到的 yield*

四、因爲數組的遍歷會調用遍歷器接口,因此任何接受數組做爲參數的場合,都默認調用,如

  for...of

  Array.from()

  Map(), Set(), WeakMap(), WeakSet()

  Promise.all()

  Promise.race()

五、字符串是一個相似數組的對象,原生也具備Iterator接口

相關文章
相關標籤/搜索