成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

ES6新特性 iterators and Generators

pf_miles / 2804人閱讀

摘要:在函數(shù)定義上使用關(guān)鍵字來表示方法調(diào)用時返回的值。是一個有屬性的。這個指向一個函數(shù),這個函數(shù)返回關(guān)于這個對象的。在中所有的集合類對象和字符串都是,并且有自己默認(rèn)的。注意本身是不返回任何值的,它只向外部產(chǎn)生值。

ES6新特性 iterators and Generators

ES6中引入了許多新特性,目前大量的JavaScript項目已經(jīng)使用了ES6來進(jìn)行開發(fā),那么熟悉這些新的特性是十分必要的,例如Redux-Saga中大量的使用了Iterator和generator。這篇文章總結(jié)和介紹一下ES6中的Iterator和Generator。

iterators and Generators

第一個問題什么是iterator?答案很簡單, Iterator是一個object,但是含有特定的接口,它有next method可以返回一個result object,這個result object有兩個屬性第一個是value,代表這個迭代的值, 第二個是done,代表迭代是否結(jié)束。如果我們自己來簡單實現(xiàn)一個Iterator,它是這樣的。

function createIterator(items) {
    var i = 0;
    return {
        next : function () {

            var done = i >= (items.length)
            var value = items[i++]

            return {
                done: done,
                value: value
            }
        }
    }
}

const items = [1,2,3]
const iteratorA = createIterator(items)
iteratorA.next() // {result:1, done: false}

那么Generator又是什么?Generator 是一個函數(shù)可以產(chǎn)生iterator。Generator函數(shù)用function關(guān)鍵字后邊帶*來表示。在函數(shù)定義上使用yield關(guān)鍵字來表示next方法調(diào)用時返回的值。例如

function *createIterator(){
    yield 1;
    yield 2;
    yield 3;
}

let iterator = createIterator();
console.log(iterator.next().value);  //1
console.log(iterator.next().value);  //2
console.log(iterator.next().value);  //3
iterables

上邊介紹了什么是Iterator,什么是generator,下邊再介紹一個概念iterable。iterable是一個有Symbol.iterator屬性的object。這個symbol指向一個generator函數(shù),這個函數(shù)返回關(guān)于這個對象的iterator。在ES6中所有的集合類對象(array, set, maps)和字符串都是iterable,并且有自己默認(rèn)的iterator。當(dāng)我們在使用 for-of時候?qū)嶋H上是利用了這些對象上的iterator,每次調(diào)用了next方法,將返回的result上的value返回回來。

let values = [1, 2, 3];
for (let num of values) { 
    console.log(num);
}

例如這段簡單的代碼,實際上調(diào)用了values上的iterator的next方法,將result上的value拿出來賦給num。既然是這樣我們可以采用這樣的方法來獲得默認(rèn)的iterator。

let values = [1, 2, 3];
let iterator = values[Symbol.iterator]();

在ES6中對于集合類型的Object,其上定義了一些內(nèi)置的iterator,分別是;

entries() - 返回一個返回key-value pair的iterator

values() - 返回一個返回collection對應(yīng)值的iterator // chrome not supported
MDN

keys() - 返回一個返回collecttion對應(yīng)key的iterator

以上就是iterator和generator的一些基本概念,下邊我們來看一下一些高階應(yīng)用。

向iterator中傳遞參數(shù)

上邊的例子中我們在調(diào)用iterator的next方法都是無參數(shù)調(diào)用的,但是我們同樣可以向next方法中傳遞參數(shù)。例如這樣。

function* createIterator() {
    let first = yield 1;
    let second = yield first + 2;
    yield second + 3;
}

let i= createItreator()

i.next() // {value:1 done: false}
i.next(5) // {value: 7 done: false}
i.next(3) // {value: 6 done: false}

我們看上邊這個例子,在第二次調(diào)用中我們傳進(jìn)去了5,返回值是7,這個傳進(jìn)去的參數(shù)可以理解為上一次yield的返回值。注意yield本身是不返回任何值的,它只向外部產(chǎn)生值。如果我們查看yield在英語詞典中的意思,produce or generate (a result, gain, or financial return 所以yield的值是向外產(chǎn)生值。所以在第一次next后 first的值依舊是undefined。但是向next中傳遞參數(shù),這個參數(shù)代表我們想要上一次yield在generator函數(shù)中的值。所以在第二次next后 返回值的value就是7(5+2)了。第三例子同理。所以基于上邊的原因我們向第一個next函數(shù)中傳入任何值都是沒有意義的。我們變化一下再看

function* createIterator() {
    yield 1;
    let first;
    let second = yield first + 2;
    yield second + 3;
}

i.next() // {value:1 done: false}
i.next(5) // {value: NaN done: false}
i.next(3) // {value: 6 done: false}

在第二個next中我們的返回是NaN, 為什么呢?這是因為first是Undefined,第一次的yield并沒有給first賦值。所以在yeild中的執(zhí)行順序是每一次執(zhí)行到相應(yīng)的yield就完了,下次繼續(xù)向下執(zhí)行。

在Iterator中Throw Error

在iterator中我們可以來throw error 來達(dá)到控制執(zhí)行的目的。例如上邊一個例子。

function* createIterator() {
    let first = yield 1;
    let second = yield first + 2;
    yield second + 3;
}

let i= createItreator()

i.next() // {value:1 done: false}
i.next(5) // {value: 7 done: false}
i.throw(new Error("error")) // error thrown done is set to true after throw error
Generator function中的Return

同樣在generator 我們可以使用 return來返回。

function* createIterator() {
    yield 1;
    return;
    yield 2;
    yield 3;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

第一次next后已經(jīng)結(jié)束了所以 我們第二次next后done就已經(jīng)是true了。

Generator 和 Iterator的應(yīng)用實例:Task Runner

我們可以使用generator和Iterator來實現(xiàn)一個task runner,可以讓我們不用手動的next,而是一次執(zhí)行結(jié)束。代碼如下:

function run(taskDef) {
    let task = taskDef();
    let value = task.next()

    function step() {
        if (!value.done) {
            value = task.next(value.value)
            step()
        }
    }

    step()
}

run(function*(){
    let first = yield 1;
    let second = yield first + 3;
    yield second + 4;
})

上邊就是一個例子,這樣定義的run function就可以順序執(zhí)行這些generator定義的步驟。

實際上generator和Iterator最為實際的作用是可以控制異步函數(shù)的執(zhí)行,下邊我們可以簡單的例子。

function run(taskDef) {
    let task = taskDef();
    let result = task.next()

    function step() {
        if (!result.done) {
            if (typeof result.value === "function") {
                result.value(function(err, data) {
                    if (err) {
                        console.log("err", err);
                        task.throw(err)
                        return
                    }
                    console.log("err", data);  
                    result = task.next(data);
                    step()
                    
                })
            } else {
                result = task.next(result.value)
                step()
            }
            
        }
    }

    step()
}

let fs = require("fs");

function readFile(filename) {
  return function (callback) {
    fs.readFile(filename, callback);
  };
}

run(function* () {
  let contents = yield readFile("abc.json");
  console.log(contents);
  console.log("Done");
});

首先我們定義了一個task runner run function 在其中當(dāng)發(fā)現(xiàn)result中的value是function的時候,就執(zhí)行這個function, 并且在異步函數(shù)的callback中,當(dāng)沒有error的時候執(zhí)行下一步。

在看我們的ReadFile function,fs模塊中的readFile是一個異步的函數(shù),而在這里我們將其進(jìn)行了封裝成為一個新的函數(shù)。讓其返回一個function給在task runner中使用。那么在我們的generator函數(shù)中,我們看上去的代碼就和同步的一樣了,先readfile,完成后將其輸出。這樣使用Iterator和generator可以幫助我們寫出一個比較好看的異步執(zhí)行函數(shù)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/83219.html

相關(guān)文章

  • ECMAScript 6特性印象之一:語法

    摘要:下例實現(xiàn)了一個數(shù)組的迭代器在中,可迭代數(shù)據(jù)結(jié)構(gòu)比如數(shù)組都必須實現(xiàn)一個名為的方法,該方法返回一個該結(jié)構(gòu)元素的迭代器。原話是還可以傳遞返回值。 前記 按照規(guī)劃,明年年中,ECMAScript 6(ES6)就要正式發(fā)布了。 最近抽空看了Dr. Axel Rauschmayer的幾篇文章和演講PPT,對新特性有了些了解。 趁沒忘,抓緊記錄下,夾雜自己的感受。 計劃分三部分: 新語法...

    馬忠志 評論0 收藏0
  • ES6 走馬觀花(ECMAScript2015 特性

    摘要:字面上是生成器的意思,在里是迭代器生成器,用于生成一個迭代器對象。當(dāng)執(zhí)行的時候,并不執(zhí)行函數(shù)體,而是返回一個迭代器。迭代器具有方法,每次調(diào)用方法,函數(shù)就執(zhí)行到語句的地方。也有觀點極力反對,認(rèn)為隱藏了本身原型鏈的語言特性,使其更難理解。 本文為 ES6 系列的第一篇。旨在給新同學(xué)一些指引,帶大家走近 ES6 新特性。簡要介紹: 什么是 ES6 它有哪些明星特性 它可以運(yùn)行在哪些環(huán)境 ...

    wangzy2019 評論0 收藏0
  • ES6(ECMAScript 6)特性

    摘要:目前的標(biāo)準(zhǔn)化工作正在進(jìn)行中,預(yù)計會在年月份放出正式敲定的版本。反的方法可以接收一個參數(shù)并且返回值取決與它的構(gòu)造函數(shù)。之后就可以用這個返回值做為對象的鍵了。 本文基于lukehoban/es6features ,同時參考了大量博客資料,具體見文末引用。 ES6(ECMAScript 6)是即將到來的新版本JavaScript語言的標(biāo)準(zhǔn),代號harmony(和諧之意,顯然沒有跟上我國的步伐...

    impig33 評論0 收藏0
  • generators(生成器)

    摘要:生成器函數(shù)是的新特性,它允許一個函數(shù)返回的可遍歷對象生成多個值。在使用中你會看到語法和一個新的關(guān)鍵詞我們在之前有認(rèn)識迭代器主要解決我們的數(shù)組遍歷方法,主要解決數(shù)組遍歷,提高了性能。 generators(生成器) Generator 函數(shù)是 ES6 的新特性,它允許一個函數(shù)返回的可遍歷對象生成多個值。 在使用中你會看到 * 語法和一個新的關(guān)鍵詞 yield: 我們在之前有認(rèn)識itera...

    FreeZinG 評論0 收藏0
  • 從0到1使用VUE-CLI3開發(fā)實戰(zhàn)(三): ES6/ES7知識儲備

    摘要:它們都用于聲明變量。盲目使用替換后可能會導(dǎo)致預(yù)期意外的結(jié)果。有鑒于此,還是建議使用字符串,布爾和數(shù)字類型的數(shù)據(jù)類型。像使用這種下劃線命名約定在一個開源項目中,命名規(guī)則很難維持得一直很好,這樣經(jīng)常會造成一些困擾。 今天群里有小伙伴跟我聊天,問了我?guī)讉€關(guān)于ES6的問題,我才意識到,大部分初學(xué)者在學(xué)習(xí)的過程中,都是學(xué)了HTML/CSS/JS之后就開始上手學(xué)習(xí)框架了,而對于ES6的重視程度卻不...

    crossoverJie 評論0 收藏0

發(fā)表評論

0條評論

pf_miles

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<