遍歷器與迭代器

Iterator

任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)。
Iterator 的作用有三個(gè):

  1. 為各種數(shù)據(jù)結(jié)構(gòu),提供一個(gè)統(tǒng)一的、簡(jiǎn)便的訪問(wèn)接口for...of
  2. 使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列;
  3. ES6 創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator 接口主要供for...of消費(fèi)。

ES6 規(guī)定,默認(rèn)的 Iterator 接口部署在數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator屬性,或者說(shuō),一個(gè)數(shù)據(jù)結(jié)構(gòu)只要具有Symbol.iterator屬性,就可以認(rèn)為是“可遍歷的”(iterable)

Iterator 接口的目的,就是為所有數(shù)據(jù)結(jié)構(gòu),提供了一種統(tǒng)一的訪問(wèn)機(jī)制,即for...of循環(huán)

let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();

iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }

生成一個(gè)Iterater

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++]} :
        {done: true};
    }
  };
}

對(duì)于普通的對(duì)象object,for...of結(jié)構(gòu)不能直接使用,會(huì)報(bào)錯(cuò),必須部署了 Iterator 接口后才能使用,主要因?yàn)閛bject是沒(méi)有順序的。如果想遍歷的話(huà),Object.keys方法將對(duì)象的鍵名生成一個(gè)數(shù)組,然后遍歷這個(gè)數(shù)組

for...of、for...in、forEach的區(qū)別
  • for...of
1. 不能遍歷對(duì)象
2. 數(shù)據(jù)結(jié)構(gòu)只要部署了Symbol.iterator屬性,就被視為具有 iterator 接口,就可以用for...of循環(huán)遍歷它的成員
3. for...of循環(huán)可以使用的范圍包括數(shù)組、Set 和 Map 結(jié)構(gòu)、某些類(lèi)似數(shù)組的對(duì)象(比如arguments對(duì)象、DOM NodeList 對(duì)象)、后文的 Generator 對(duì)象,以及字符串

遍歷鍵值鍵名的方式
let arr = ['a', 'b', 'c'];
for (let pair of arr.entries()) {
  console.log(pair);
}
// [0, 'a']
// [1, 'b']
// [2, 'c']

  • for...in
1. 數(shù)組的鍵名是數(shù)字,但是for...in循環(huán)是以字符串作為鍵名“0”、“1”、“2”等等。
2. for...in循環(huán)不僅遍歷數(shù)字鍵名,還會(huì)遍歷手動(dòng)添加的其他鍵,甚至包括原型鏈上的鍵。
3. for...in循環(huán)會(huì)以任意順序遍歷鍵名,適合遍歷對(duì)象,不適合遍歷數(shù)組
  • forEach
1. 無(wú)法中途跳出forEach循環(huán),break命令或return命令都不能奏效

Generater

  • Generator 函數(shù)是 ES6 提供的一種異步編程解決方案

Generator 函數(shù)返回的遍歷器對(duì)象,只有調(diào)用next方法才會(huì)遍歷下一個(gè)內(nèi)部狀態(tài),所以其實(shí)提供了一種可以暫停執(zhí)行的函數(shù)。yield表達(dá)式就是暫停標(biāo)志。

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}
var hw = helloWorldGenerator();// 返回一個(gè)遍歷器對(duì)象 (Iterator Object)
hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }
  • yield 表達(dá)式

每次遇到y(tǒng)ield,函數(shù)暫停執(zhí)行,下一次再?gòu)脑撐恢美^續(xù)向后執(zhí)行(異步可中斷,與react的機(jī)制相同,但是會(huì)引進(jìn)新的副作用,所以沒(méi)被react采用)。

  • 與 Iterator 接口的關(guān)系
    Generator 函數(shù)執(zhí)行后,返回一個(gè)遍歷器對(duì)象。該對(duì)象本身也具有Symbol.iterator屬性,執(zhí)行后返回自身。
function* gen(){
  // some code
}
var g = gen();
g[Symbol.iterator]() === g
// true

Generater的異步應(yīng)用

  • 異步編程的方法
  1. 回調(diào)函數(shù)
  2. 事件監(jiān)聽(tīng)
  3. 發(fā)布/訂閱
  4. Promise 對(duì)象
  5. Generater
  6. async...await
  • 協(xié)程
    意思是多個(gè)線(xiàn)程互相協(xié)作,完成異步任務(wù)
var fetch = require('node-fetch');
function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});
  • Thunk 函數(shù)
    任何函數(shù),只要參數(shù)有回調(diào)函數(shù),就能寫(xiě)成 Thunk 函數(shù)的形式
const Thunk = function(fn) {
  return function (...args) {
    return function (callback) {
      return fn.call(this, ...args, callback);
    }
  };
};
var readFileThunk = Thunk(fs.readFile);
readFileThunk(fileA)(callback);

基于 Thunk 函數(shù)的 Generator 執(zhí)行器

function run(fn) {
  var gen = fn();

  function next(err, data) {
    var result = gen.next(data);
    if (result.done) return;
    result.value(next);
  }

  next();
}

function* g() {
  // ...
}

run(g);

CO模塊自動(dòng)執(zhí)行

function run(gen){
  var g = gen();

  function next(data){
    var result = g.next(data);
    if (result.done) return result.value;
    result.value.then(function(data){
      next(data);
    });
  }

  next();
}

run(gen);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容