<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        JavaScript中的迭代器和生成器詳解_javascript技巧

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 21:28:13
        文檔

        JavaScript中的迭代器和生成器詳解_javascript技巧

        JavaScript中的迭代器和生成器詳解_javascript技巧:處理集合里的每一項(xiàng)是一個(gè)非常普通的操作,JavaScript提供了許多方法來(lái)迭代一個(gè)集合,從簡(jiǎn)單的for和for each循環(huán)到 map(),filter() 和 array comprehensions(數(shù)組推導(dǎo)式)。在JavaScript 1.7中,迭代器和生成器在JavaScript核心語(yǔ)法中帶來(lái)了新
        推薦度:
        導(dǎo)讀JavaScript中的迭代器和生成器詳解_javascript技巧:處理集合里的每一項(xiàng)是一個(gè)非常普通的操作,JavaScript提供了許多方法來(lái)迭代一個(gè)集合,從簡(jiǎn)單的for和for each循環(huán)到 map(),filter() 和 array comprehensions(數(shù)組推導(dǎo)式)。在JavaScript 1.7中,迭代器和生成器在JavaScript核心語(yǔ)法中帶來(lái)了新

        處理集合里的每一項(xiàng)是一個(gè)非常普通的操作,JavaScript提供了許多方法來(lái)迭代一個(gè)集合,從簡(jiǎn)單的for和for each循環(huán)到 map(),filter() 和 array comprehensions(數(shù)組推導(dǎo)式)。在JavaScript 1.7中,迭代器和生成器在JavaScript核心語(yǔ)法中帶來(lái)了新的迭代機(jī)制,而且還提供了定制 for…in 和 for each 循環(huán)行為的機(jī)制。

        迭代器

        迭代器是一個(gè)每次訪問(wèn)集合序列中一個(gè)元素的對(duì)象,并跟蹤該序列中迭代的當(dāng)前位置。在JavaScript中迭代器是一個(gè)對(duì)象,這個(gè)對(duì)象提供了一個(gè) next() 方法,next() 方法返回序列中的下一個(gè)元素。當(dāng)序列中所有元素都遍歷完成時(shí),該方法拋出 StopIteration 異常。

        迭代器對(duì)象一旦被建立,就可以通過(guò)顯式的重復(fù)調(diào)用next(),或者使用JavaScript的 for…in 和 for each 循環(huán)隱式調(diào)用。

        簡(jiǎn)單的對(duì)對(duì)象和數(shù)組進(jìn)行迭代的迭代器可以使用 Iterator() 被創(chuàng)建:

        代碼如下:
        var lang = { name: 'JavaScript', birthYear: 1995 };
        var it = Iterator(lang);

        一旦初始化完成,next() 方法可以被調(diào)用來(lái)依次訪問(wèn)對(duì)象的鍵值對(duì):

        代碼如下:
        var pair = it.next(); //鍵值對(duì)是["name", "JavaScript"]
        pair = it.next(); //鍵值對(duì)是["birthday", 1995]
        pair = it.next(); //一個(gè) `StopIteration` 異常被拋出

        for…in 循環(huán)可以被用來(lái)替換顯式的調(diào)用 next() 方法。當(dāng) StopIteration 異常被拋出時(shí),循環(huán)會(huì)自動(dòng)終止。

        代碼如下:
        var it = Iterator(lang);
        for (var pair in it)
        print(pair); //每次輸出 it 中的一個(gè) [key, value] 鍵值對(duì)

        如果你只想迭代對(duì)象的 key 值,可以往 Iterator() 函數(shù)中傳入第二個(gè)參數(shù),值為 true:

        代碼如下:
        var it = Iterator(lang, true);
        for (var key in it)
        print(key); //每次輸出 key 值

        使用 Iterator() 訪問(wèn)對(duì)象的一個(gè)好處是,被添加到 Object.prototype 的自定義屬性不會(huì)被包含在序列對(duì)象中。

        Iterator() 同樣可以被作用在數(shù)組上:

        代碼如下:
        var langs = ['JavaScript', 'Python', 'Haskell'];
        var it = Iterator(langs);
        for (var pair in it)
        print(pair); //每次迭代輸出 [index, language] 鍵值對(duì)

        就像遍歷對(duì)象一樣,把 true 當(dāng)做第二個(gè)參數(shù)傳入遍歷的結(jié)果將會(huì)是數(shù)組索引:

        代碼如下:
        var langs = ['JavaScript', 'Python', 'Haskell'];
        var it = Iterator(langs, true);
        for (var i in it)
        print(i); //輸出 0,然后是 1,然后是 2

        使用 let 關(guān)鍵字可以在循環(huán)內(nèi)部分別分配索引和值給塊變量,還可以解構(gòu)賦值(Destructuring Assignment):

        代碼如下:
        var langs = ['JavaScript', 'Python', 'Haskell'];
        var it = Iterators(langs);
        for (let [i, lang] in it)
        print(i + ': ' + lang); //輸出 "0: JavaScript" 等

        聲明自定義迭代器

        一些代表元素集合的對(duì)象應(yīng)該用一種指定的方式來(lái)迭代。

        1.迭代一個(gè)表示范圍(Range)的對(duì)象應(yīng)該一個(gè)接一個(gè)的返回這個(gè)范圍包含的數(shù)字
        2.一個(gè)樹(shù)的葉子節(jié)點(diǎn)可以使用深度優(yōu)先或者廣度優(yōu)先訪問(wèn)到
        3.迭代一個(gè)代表數(shù)據(jù)庫(kù)查詢結(jié)果的對(duì)象應(yīng)該一行一行的返回,即使整個(gè)結(jié)果集尚未全部加載到一個(gè)單一數(shù)組
        4.作用在一個(gè)無(wú)限數(shù)學(xué)序列(像斐波那契序列)上的迭代器應(yīng)該在不創(chuàng)建無(wú)限長(zhǎng)度數(shù)據(jù)結(jié)構(gòu)的前提下一個(gè)接一個(gè)的返回結(jié)果

        JavaScript 允許你寫自定義迭代邏輯的代碼,并把它作用在一個(gè)對(duì)象上

        我們創(chuàng)建一個(gè)簡(jiǎn)單的 Range 對(duì)象,包含低和高兩個(gè)值:

        代碼如下:
        function Range(low, high){
        this.low = low;
        this.high = high;
        }

        現(xiàn)在我們創(chuàng)建一個(gè)自定義迭代器,它返回一個(gè)包含范圍內(nèi)所有整數(shù)的序列。迭代器接口需要我們提供一個(gè) next() 方法用來(lái)返回序列中的下一個(gè)元素或者是拋出 StopIteration 異常。

        代碼如下:
        function RangeIterator(range){
        this.range = range;
        this.current = this.range.low;
        }
        RangeIterator.prototype.next = function(){
        if (this.current > this.range.high)
        throw StopIteration;
        else
        return this.current++;
        };

        我們的 RangeIterator 通過(guò) range 實(shí)例來(lái)實(shí)例化,同時(shí)維持一個(gè) current 屬性來(lái)跟蹤當(dāng)前序列的位置。

        最后,為了讓 RangeIterator 可以和 Range 結(jié)合起來(lái),我們需要為 Range 添加一個(gè)特殊的 __iterator__ 方法。當(dāng)我們?cè)噲D去迭代一個(gè) Range 時(shí),它將被調(diào)用,而且應(yīng)該返回一個(gè)實(shí)現(xiàn)了迭代邏輯的 RangeIterator 實(shí)例。

        代碼如下:
        Range.prototype.__iterator__ = function(){
        return new RangeIterator(this);
        };

        完成我們的自定義迭代器后,我們就可以迭代一個(gè)范圍實(shí)例:

        代碼如下:
        var range = new Range(3, 5);
        for (var i in range)
        print(i); //輸出 3,然后 4,然后 5

        生成器:一種更好的方式來(lái)構(gòu)建迭代器

        雖然自定義的迭代器是一種很有用的工具,但是創(chuàng)建它們的時(shí)候要仔細(xì)規(guī)劃,因?yàn)樾枰@式的維護(hù)它們的內(nèi)部狀態(tài)。

        生成器提供了很強(qiáng)大的功能:它允許你定義一個(gè)包含自有迭代算法的函數(shù), 同時(shí)它可以自動(dòng)維護(hù)自己的狀態(tài)。

        生成器是可以作為迭代器工廠的特殊函數(shù)。如果一個(gè)函數(shù)包含了一個(gè)或多個(gè) yield 表達(dá)式,那么就稱它為生成器(譯者注:Node.js 還需要在函數(shù)名前加 * 來(lái)表示)。

        注意:只有 HTML 中被包含在 輸出 "first"
        print(g.next()); //輸出 "second"
        print(g.next()); //輸出 "third"
        print(g.next()); //輸出 0
        print(g.next()); //輸出 1
        print(g.next()); //輸出 2
        print(g.next()); //拋出 StopIteration 異常

        生成器函數(shù)可以被一個(gè)類直接的當(dāng)做 __iterator__ 方法使用,在需要自定義迭代器的地方可以有效的減少代碼量。我們使用生成器重寫一下 Range :
        代碼如下:
        function Range(low, high){
        this.low = low;
        this.high = high;
        }
        Range.prototype.__iterator__ = function(){
        for (var i = this.low; i <= this.high; i++)
        yield i;
        };
        var range = new Range(3, 5);
        for (var i in range)
        print(i); //輸出 3,然后 4,然后 5

        不是所有的生成器都會(huì)終止,你可以創(chuàng)建一個(gè)代表無(wú)限序列的生成器。下面的生成器實(shí)現(xiàn)一個(gè)斐波那契序列,就是每一個(gè)元素都是前面兩個(gè)的和:
        代碼如下:
        function fibonacci(){
        var fn1 = 1;
        var fn2 = 1;
        while (1) {
        var current = fn2;
        fn2 = fn1;
        fn1 = fn1 + current;
        yield current;
        }
        }

        var sequence = fibonacci();
        print(sequence.next()); // 1
        print(sequence.next()); // 1
        print(sequence.next()); // 2
        print(sequence.next()); // 3
        print(sequence.next()); // 5
        print(sequence.next()); // 8
        print(sequence.next()); // 13

        生成器函數(shù)可以帶有參數(shù),并且會(huì)在第一次調(diào)用函數(shù)時(shí)使用這些參數(shù)。生成器可以被終止(引起它拋出 StopIteration 異常)通過(guò)使用 return 語(yǔ)句。下面的 fibonacci() 變體帶有一個(gè)可選的 limit 參數(shù),當(dāng)條件被觸發(fā)時(shí)終止函數(shù)。

        代碼如下:
        function fibonacci(limit){
        var fn1 = 1;
        var fn2 = 1;
        while(1){
        var current = fn2;
        fn2 = fn1;
        fn1 = fn1 + current;
        if (limit && current > limit)
        return;
        yield current;
        }
        }

        生成器高級(jí)特性

        生成器可以根據(jù)需求計(jì)算yield返回值,這使得它可以表示以前昂貴的序列計(jì)算需求,甚至是上面所示的無(wú)限序列。

        除了 next() 方法,generator-iterator 對(duì)象還有一個(gè) send() 方法,該方法可以修改生成器的內(nèi)部狀態(tài)。傳給 send() 的值將會(huì)被當(dāng)做最后一個(gè) yield 表達(dá)式的結(jié)果,并且會(huì)暫停生成器。在你使用 send() 方法傳一個(gè)指定值前,你必須至少調(diào)用一次 next() 來(lái)啟動(dòng)生成器。

        下面的斐波那契生成器使用 send() 方法來(lái)重啟序列:

        代碼如下:
        function fibonacci(){
        var fn1 = 1;
        var fn2 = 1;
        while (1) {
        var current = fn2;
        fn2 = fn1;
        fn1 = fn1 + current;
        var reset = yield current;
        if (reset) {
        fn1 = 1;
        fn2 = 1;
        }
        }
        }

        var sequence = fibonacci();
        print(sequence.next()); //1
        print(sequence.next()); //1
        print(sequence.next()); //2
        print(sequence.next()); //3
        print(sequence.next()); //5
        print(sequence.next()); //8
        print(sequence.next()); //13
        print(sequence.send(true)); //1
        print(sequence.next()); //1
        print(sequence.next()); //2
        print(sequence.next()); //3

        注意:有意思的一點(diǎn)是,調(diào)用 send(undefined) 和調(diào)用 next() 是完全同等的。不過(guò),當(dāng)調(diào)用 send() 方法啟動(dòng)一個(gè)新的生成器時(shí),除了 undefined 其它的值都會(huì)拋出一個(gè) TypeError 異常。

        你可以調(diào)用 throw 方法并且傳遞一個(gè)它應(yīng)該拋出的異常值來(lái)強(qiáng)制生成器拋出一個(gè)異常。此異常將從當(dāng)前上下文拋出并暫停生成器,類似當(dāng)前的 yield 執(zhí)行,只不過(guò)換成了 throw value 語(yǔ)句。

        如果在拋出異常的處理過(guò)程中沒(méi)有遇到 yield ,該異常將會(huì)被傳遞直到調(diào)用 throw() 方法,并且隨后調(diào)用 next() 將會(huì)導(dǎo)致 StopIteration 異常被拋出。

        生成器擁有一個(gè) close() 方法來(lái)強(qiáng)制生成器結(jié)束。結(jié)束一個(gè)生成器會(huì)產(chǎn)生如下影響:

        1.所有生成器中有效的 finally 字句將會(huì)執(zhí)行
        2.如果 finally 字句拋出了除 StopIteration 以外的任何異常,該異常將會(huì)被傳遞到 close() 方法的調(diào)用者
        3.生成器會(huì)終止

        生成器表達(dá)式

        數(shù)組推導(dǎo)式 的一個(gè)明顯缺點(diǎn)是,它們會(huì)導(dǎo)致整個(gè)數(shù)組在內(nèi)存中構(gòu)造。當(dāng)輸入到推導(dǎo)式的本身是個(gè)小數(shù)組時(shí)它的開(kāi)銷是微不足道的—但是,當(dāng)輸入數(shù)組很大或者創(chuàng)建一個(gè)新的昂貴(或者是無(wú)限的)數(shù)組生成器時(shí)就可能出現(xiàn)問(wèn)題。

        生成器允許對(duì)序列延遲計(jì)算(lazy computation),在需要時(shí)按需計(jì)算元素。生成器表達(dá)式在句法上幾乎和數(shù)組推導(dǎo)式相同—它用圓括號(hào)來(lái)代替方括號(hào)(而且用 for...in 代替 for each...in)—但是它創(chuàng)建一個(gè)生成器而不是數(shù)組,這樣就可以延遲計(jì)算。你可以把它想象成創(chuàng)建生成器的簡(jiǎn)短語(yǔ)法。

        假設(shè)我們有一個(gè)迭代器 it 來(lái)迭代一個(gè)巨大的整數(shù)序列。我們需要?jiǎng)?chuàng)建一個(gè)新的迭代器來(lái)迭代偶數(shù)。一個(gè)數(shù)組推導(dǎo)式將會(huì)在內(nèi)存中創(chuàng)建整個(gè)包含所有偶數(shù)的數(shù)組:
        代碼如下:
        var doubles = [i * 2 for (i in it)];

        而生成器表達(dá)式將會(huì)創(chuàng)建一個(gè)新的迭代器,并且在需要的時(shí)候按需來(lái)計(jì)算偶數(shù)值:
        代碼如下:
        var it2 = (i * 2 for (i in it));
        print(it2.next()); //it 里面的第一個(gè)偶數(shù)
        print(it2.next()); //it 里面的第二個(gè)偶數(shù)

        當(dāng)一個(gè)生成器被用做函數(shù)的參數(shù),圓括號(hào)被用做函數(shù)調(diào)用,意味著最外層的圓括號(hào)可以被省略:

        代碼如下:
        var result = doSomething(i * 2 for (i in it));

        End.

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        JavaScript中的迭代器和生成器詳解_javascript技巧

        JavaScript中的迭代器和生成器詳解_javascript技巧:處理集合里的每一項(xiàng)是一個(gè)非常普通的操作,JavaScript提供了許多方法來(lái)迭代一個(gè)集合,從簡(jiǎn)單的for和for each循環(huán)到 map(),filter() 和 array comprehensions(數(shù)組推導(dǎo)式)。在JavaScript 1.7中,迭代器和生成器在JavaScript核心語(yǔ)法中帶來(lái)了新
        推薦度:
        標(biāo)簽: js 生成器 javascript
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 精品国产精品久久一区免费式| 精品福利一区二区三区免费视频| 久久国产精品免费一区二区三区| 免费精品无码AV片在线观看 | 黄网站免费在线观看| 中文字幕免费在线看线人| 亚洲欧洲第一a在线观看| 亚洲成av人片天堂网无码】| 精品国产一区二区三区免费| 亚洲精品无码永久中文字幕| 大桥未久亚洲无av码在线| 久热中文字幕在线精品免费| 亚洲精品伊人久久久久| 69视频在线观看免费| 亚洲欧洲日产国码av系列天堂| 人人狠狠综合久久亚洲| 中国xxxxx高清免费看视频| 亚洲伊人久久精品影院| 久久99毛片免费观看不卡| 亚洲熟妇色自偷自拍另类| 久久免费福利视频| 亚洲中文字幕无码日韩| 污视频网站免费在线观看| 国产成人无码a区在线观看视频免费| 亚洲人成777在线播放| 最近中文字幕2019高清免费| 亚洲视频一区二区三区四区| 国产成人在线免费观看| a级毛片无码免费真人久久| 亚洲精品无码久久久| 黄网站色视频免费观看45分钟| 拨牐拨牐x8免费| 亚洲美女视频免费| 国产精品99久久免费观看| 亚洲jjzzjjzz在线观看| 美女视频黄免费亚洲| 精品亚洲AV无码一区二区| 亚洲Av无码乱码在线观看性色 | 久久精品熟女亚洲av麻豆| 国产成A人亚洲精V品无码性色| 国产精品免费久久久久久久久 |