ES6迭代器簡介

簡單介紹下 ES6 規(guī)范里面迭代器(Iterator)相關(guān)的概念梅肤。最近為啥會看到迭代器,是因?yàn)榭戳?fetch 相關(guān)的 Headers 接口邑茄,為了實(shí)現(xiàn)下 Headers 接口就涉及到了迭代器姨蝴。

迭代器(Iterator)

為什么要有迭代器,是為了給不同的數(shù)據(jù)結(jié)構(gòu)一個統(tǒng)一的迭代方法肺缕,不管你是一個 Array 還是一個 Queue 還是一個 Dictionary左医,反正只要你提供了符合規(guī)范的迭代器,程序員就能通過統(tǒng)一的方法來迭代你這個數(shù)據(jù)結(jié)構(gòu)同木。迭代器是一個實(shí)現(xiàn)了 Iterator 接口的對象浮梢。接口指定迭代器對象必須實(shí)現(xiàn)一個 next 方法,如下示例偽代碼彤路。

var iterator = {
  next: function() {
    // impl
  }
}

next 方法是否接受參數(shù)黔寇,在規(guī)范中并不嚴(yán)格限定,取決于實(shí)現(xiàn)當(dāng)前這個迭代器的對象斩萌。但是必須能接受無參數(shù)的情況缝裤,因?yàn)?ES6 語法使用迭代器的時候是不會傳參數(shù)的屏轰,譬如 for-of。next 方法返回的數(shù)據(jù)結(jié)構(gòu)是 {done:boolean, value:ES6value}憋飞。每次調(diào)用 next霎苗,如果與之關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu)里面有數(shù)據(jù),那么按照當(dāng)前數(shù)據(jù)結(jié)構(gòu)自己的規(guī)則把當(dāng)前被迭代到的元素放到返回的數(shù)據(jù)結(jié)構(gòu)的 value 值中榛做,done 填寫 false唁盏。done 標(biāo)識是否迭代到了最后。當(dāng)?shù)阶詈笠粋€元素后检眯,再調(diào)用一次 next 后厘擂,返回的 done 就應(yīng)該是 true。用代碼示例下:

function getArrayIterator( array ) {
  // 等下再說
}

var iterator = getArrayIterator( [1, 2, 3, 4] );
iterator.next(); // { done: false, value: 1 }
iterator.next(); // { done: false, value: 2 }
iterator.next(); // { done: false, value: 3 }
iterator.next(); // { done: false, value: 4 }
iterator.next(); // { done: true, value: undefined }
iterator.next(); // { done: true, value: undefined }

當(dāng)?shù)饕呀?jīng)迭代完最后一個元素锰瘸,那么無論調(diào)用幾次 next 返回的 done 都是 true刽严。不過規(guī)范里面說,如果在迭代的過程中避凝,next 返回的數(shù)據(jù)結(jié)構(gòu)中沒有 done 這個屬性的話舞萄,我們應(yīng)該視作其值是 false。再來看看 value管削,其取值可以是規(guī)范中的任意類型倒脓。當(dāng)?shù)阶詈笠粋€元素后,即 done:true 的時候含思,value 可以是 undefined崎弃,也可以被填入一個返回值。MDN 中加了一篇文章的鏈接來說明當(dāng) done:true 時候含潘,value 如果被設(shè)成有一個 returnValue 的意義饲做,不過我英語比較挫真心沒有看懂,只能列下原文引用:

Why can iterators (optionally) return a value after the last element? That capability is the reason for elements being wrapped. Otherwise, iterators could simply return a publicly defined sentinel (stop value) after the last element.

可迭代對象(Iterable)

迭代器是通過可迭代對象獲得的调鬓,譬如數(shù)組就是一個可迭代對象。那么如何通過可迭代對象獲得迭代器呢酌伊?規(guī)范中規(guī)定可迭代對象必須實(shí)現(xiàn)一個名為 @@iterator 的方法腾窝,調(diào)用這個方法返回和當(dāng)前對象掛鉤的迭代器,譬如:

function getArrayIterator( array ) {
  return array[ '@@iterator' ]();
}

var iterator = getArrayIterator( [1, 2, 3, 4] );

但是 @@iterator 方法的名字并不是一個 string居砖,而是 Symbol.iterator虹脯。Symbol 是ES6 引入的一個新的類型,表示一個獨(dú)一無二的值(這里就不展開了)奏候。所以上例獲取迭代器不是正確的寫法循集,正確的應(yīng)該是:

function getArrayIterator( array ) {
  return array[ Symbol.iterator ]();
}

var iterator = getArrayIterator( [1, 2, 3, 4] );

ES6 中新加了一些針對可迭代對象的語法,譬如 for-of:

var array = [ 1, 2, 3 ];
for ( let i of array ) {
  console.log( i );
}
// 輸出
// 1
// 2
// 3

/* 上面的 for-of 和下面的代碼等價 */
var iterator = array[ Symbol.iterator ]();
var iteratorResult = iterator.next();
while( !iteratorResult.done ) {
  console.log( iteratorResult.value );
  iteratorResult = iterator.next();
}

迭代器(Iterator)可選屬性

其實(shí)迭代器除了規(guī)定一定要實(shí)現(xiàn)的 next 方法蔗草,還有兩個是可選實(shí)現(xiàn)的方法 return 和 throw咒彤。

return

return 方法如果被調(diào)用疆柔,意味著調(diào)用者要終結(jié)此次迭代。return 返回一個 {done:true, value:arg} 對象镶柱,value 是調(diào)用 return 方法時傳入的參數(shù)旷档,即:

var iterator = {
  next: function() {
    // impl
  },
  return: function( arg ) {
    return {
      done: true,
      value: arg
    }
  }
}

return 方法被調(diào)用后,后續(xù)再調(diào)用當(dāng)前迭代器的 next 方法歇拆,返回的對象 done 一律為 true鞋屈。

throw

throw 方法如果被調(diào)用,表示迭代的過程中檢測到了異常故觅。一般來說 throw 方法傳入的參數(shù)就是錯誤對象(但是這個不是強(qiáng)制規(guī)定的)厂庇。throw 方法的通常行為應(yīng)該是以拋出異常的方式拋出傳入的對象,但是這個行為也是建議不強(qiáng)制输吏。如果 throw 方法不拋出異常权旷,那么返回值為 {done:true}。表示迭代終結(jié)评也,后續(xù)再調(diào)用當(dāng)前迭代器的 next 方法炼杖,返回的對象 done 一律為 true。

因?yàn)?return 和 throw 兩個方法是可選實(shí)現(xiàn)的盗迟,所以在調(diào)用迭代器這個兩個方法前坤邪,都要檢測這兩個方法是否存在。


2017.4.6 補(bǔ)充:
規(guī)范里面指出罚缕,迭代器也必須是一個可迭代的對象艇纺,即:

iterator = {
  next: function() {

  },
  [Symbol.iterator]: function() {
    return this;
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市邮弹,隨后出現(xiàn)的幾起案子黔衡,更是在濱河造成了極大的恐慌,老刑警劉巖腌乡,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盟劫,死亡現(xiàn)場離奇詭異,居然都是意外死亡与纽,警方通過查閱死者的電腦和手機(jī)侣签,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來急迂,“玉大人影所,你說我怎么就攤上這事×潘椋” “怎么了猴娩?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我卷中,道長矛双,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任仓坞,我火速辦了婚禮背零,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘无埃。我一直安慰自己徙瓶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布嫉称。 她就那樣靜靜地躺著侦镇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪织阅。 梳的紋絲不亂的頭發(fā)上壳繁,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機(jī)與錄音荔棉,去河邊找鬼闹炉。 笑死,一個胖子當(dāng)著我的面吹牛润樱,可吹牛的內(nèi)容都是我干的渣触。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼壹若,長吁一口氣:“原來是場噩夢啊……” “哼嗅钻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起店展,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤养篓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赂蕴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柳弄,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年概说,在試婚紗的時候發(fā)現(xiàn)自己被綠了碧注。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡席怪,死狀恐怖应闯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤茴丰,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布督函,位于F島的核電站假消,受9級特大地震影響浸遗,放射性物質(zhì)發(fā)生泄漏埠通。R本人自食惡果不足惜骑祟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一声怔、第九天 我趴在偏房一處隱蔽的房頂上張望态贤。 院中可真熱鬧,春花似錦醋火、人聲如沸悠汽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柿冲。三九已至,卻和暖如春兆旬,著一層夾襖步出監(jiān)牢的瞬間假抄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工丽猬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宿饱,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓脚祟,卻偏偏與公主長得像谬以,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子愚铡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容