国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ES6——生成器

cgh1999520 / 1252人閱讀

摘要:我們還能如何使用生成器作為迭代器的能力使對(duì)象可迭代。一些重要的事件值得了解生成器是由布倫丹艾希首次在上實(shí)現(xiàn)的。布倫丹艾希的設(shè)計(jì)是緊緊跟隨由啟發(fā)的生成器。

什么是生成器?

我們先從下面的這里例子開始。

function* quips(name) {
  yield "hello " + name + "!";
  yield "i hope you are enjoying the blog posts";
  if (name.startsWith("X")) {
    yield "it"s cool how your name starts with X, " + name;
  }
  yield "see you later!";
}

這段代碼是一個(gè)對(duì)話貓,這可能是當(dāng)前網(wǎng)絡(luò)上最重要的一類應(yīng)用。

這個(gè)在一定程度上看起來像一個(gè)函數(shù),對(duì)不?這就被稱為生成器函數(shù),同時(shí)它與函數(shù)之間也有很多相似之處。但是你一下子就能發(fā)現(xiàn)兩個(gè)不同之處:

普通的函數(shù)使用function作為開始。生成器函數(shù)以function*開始。 在一個(gè)生成器函數(shù)中,yield是一個(gè)關(guān)鍵字,語法和return很相似。 區(qū)別在于,一個(gè)函數(shù)(甚至是生成器函數(shù)),只能返回一次,但是一個(gè)生成器函數(shù)能夠yield很多次。 yield表達(dá)式暫停生成器的運(yùn)行,然后它能夠在之后重新被使用。 就是這樣的,以上就是普通的函數(shù)和生成器函數(shù)之間的大區(qū)別。普通的函數(shù)不能自己暫停。然而生成器函數(shù)可以自己暫停運(yùn)行。

生成器的用處

當(dāng)你調(diào)用quips()生成器函數(shù)時(shí)將會(huì)發(fā)生什么?

> var iter = quips("jorendorff");
  [object Generator]
> iter.next()
  { value: "hello jorendorff!", done: false }
> iter.next()
  { value: "i hope you are enjoying the blog posts", done: false }
> iter.next()
  { value: "see you later!", done: false }
> iter.next()
  { value: undefined, done: true }

你可能非常習(xí)慣于普通的函數(shù)以及他們的表現(xiàn)。當(dāng)你調(diào)用他們的時(shí)候,他們立即開始運(yùn)行,當(dāng)遇到 return或者throw的時(shí)候,他們停止運(yùn)行。任何一個(gè)JS程序員都非常習(xí)慣于上述的過程。

調(diào)用一個(gè)生成器看起來是一樣的:quips(”jorendorff”)。 但是當(dāng)你調(diào)用一個(gè)生成器,他還不開始運(yùn)行。反而,它返回一個(gè)暫停的生成器對(duì)象(在上述的例子中被稱為iter)。你可以認(rèn)為這個(gè)生成器對(duì)象是一個(gè)函數(shù)調(diào)用,暫時(shí)停止。特別的是,其在生成器函數(shù)一開始就停止了,在運(yùn)行代碼的第一行之前。

每次你調(diào)用生成器對(duì)象的.next()方法,函數(shù)將其自己解凍并運(yùn)行直到其到達(dá)下一個(gè)yield表達(dá)式。

這就是上面代碼中我們?yōu)槭裁匆{(diào)用iter.next(),調(diào)用后我們獲得一個(gè)不同的字符串值。這些值都是由quips()里的yield表達(dá)式產(chǎn)生的。

在最后一個(gè)iter.next( )調(diào)用中,我們最后結(jié)束了生成器函數(shù),所以結(jié)果的.done領(lǐng)域的值為true。 一個(gè)函數(shù)的結(jié)束就像是返回undefined,而且這也是為什么結(jié)果的.value領(lǐng)域是不確定的。

現(xiàn)在可能是一個(gè)好機(jī)會(huì)來返回到上面的對(duì)話貓的例子那頁面上,同時(shí)真正地可以玩轉(zhuǎn)代碼。嘗試著在一個(gè)循環(huán)中加入一個(gè)yield。這會(huì)發(fā)生什么呢?

在技術(shù)層面上,每一次一個(gè)生成器進(jìn)行yield操作,其堆棧楨,包括局部變量,參數(shù),臨時(shí)值,以及在生成器中的執(zhí)行的當(dāng)前位置,被從棧中刪除。然而,生成器對(duì)象保有這個(gè)堆棧幀的引用(或者是副本)。因此,接下來的調(diào)用.next( )可以重新激活它并繼續(xù)執(zhí)行。

值得指出的是,生成器都沒有線程。在能使用線程的語言中,多份代碼可以在同一時(shí)間運(yùn)行,這通常導(dǎo)致了競爭條件,非確定性和非常非常好的性能。生成器和這完全不同。當(dāng)生成器運(yùn)行時(shí),它與調(diào)用者運(yùn)行在同一個(gè)線程中。執(zhí)行的順序是連續(xù)且確定的,并永遠(yuǎn)不會(huì)并發(fā)。不同于系統(tǒng)線程,生成器只會(huì)在代碼中用yield標(biāo)記的地方才會(huì)懸掛。

好了。我們知道生成器是什么了。我們已經(jīng)看到了生成器器運(yùn)行,暫停,然后恢復(fù)執(zhí)行。現(xiàn)在的大問題是,這樣奇怪的能力怎么可能是有用的呢?

生成器是迭代器,我們已經(jīng)看到了ES6的迭代器不只是一個(gè)簡單的內(nèi)置類。他們是語言的擴(kuò)展點(diǎn)。你可以通過實(shí)現(xiàn)兩種方法來創(chuàng)建你自己的迭代器,這兩種方法是:Symbol.iterator和.next()。

但是,實(shí)現(xiàn)接口總是至少還是有一點(diǎn)工作量的。讓我們來看看一個(gè)迭代器實(shí)現(xiàn)在實(shí)踐中看起來是什么樣的。因?yàn)槭且粋€(gè)例子,讓我們使用一個(gè)簡單的范圍(range)迭代器,只簡單的從一個(gè)數(shù)字?jǐn)?shù)到另一個(gè)數(shù)字,就像一個(gè)老式的C語言的for(;;)循環(huán)。

// 這個(gè)應(yīng)該三次發(fā)出“叮”的聲音

for (var value of range(0, 3)) {
  alert("Ding! at floor #" + value);
}

這里是一個(gè)使用ES6的類的解決方案。

class RangeIterator {
  constructor(start, stop) {
    this.value = start;
    this.stop = stop;
  }

  [Symbol.iterator]() { return this; }

  next() {
    var value = this.value;
    if (value < this.stop) {
      this.value++;
      return {done: false, value: value};
    } else {
      return {done: true, value: undefined};
    }
  }
}
// 返回一個(gè)新的從“開始”數(shù)到“結(jié)束”的迭代器。

function range(start, stop) {
  return new RangeIterator(start, stop);
}

在實(shí)際運(yùn)行中看這段代碼(http://codepen.io/anon/pen/NqGgOQ)。

這就是像是在Java或Swift語言里實(shí)現(xiàn)一個(gè)迭代器。它不是那么糟糕。但它也并不是那么簡單。在這個(gè)代碼中有沒有任何錯(cuò)誤?這就不好說了。它看起來完全不像我們想在這里模仿的原來的for(;;)循環(huán):迭代器協(xié)議迫使我們拋棄了循環(huán)。

在這一點(diǎn)上,你可能會(huì)對(duì)迭代器不太熱情。他們可能對(duì)使用來說很棒,但他們似乎很難實(shí)現(xiàn)。

你可能不會(huì)建議我們只是為了簡單的創(chuàng)建迭代器,而在JS語言中引進(jìn)一個(gè)復(fù)雜的新的控制流結(jié)構(gòu)。但是,因?yàn)槲覀兇_實(shí)有生成器,我們能在這里使用它們嗎?讓我們?cè)囈辉嚕?/p>

function* range(start, stop) {
  for (var i = start; i < stop; i++)
    yield i;
}

在這里看代碼的具體運(yùn)行(http://codepen.io/anon/pen/mJewga)。

上述的四行的生成器是對(duì)先前range()的二十三行的實(shí)現(xiàn)的一個(gè)直接替代,包括了整個(gè)RangeIterator類。這可能是因?yàn)樯善魇堑鳌K械纳善鞫加幸粋€(gè)內(nèi)置的對(duì).next()已經(jīng)Symbol.iterator方法的實(shí)現(xiàn)。

不使用生成器來實(shí)現(xiàn)迭代器就像是被強(qiáng)迫用被動(dòng)語氣寫一封很長的郵件。本來想簡單地想表達(dá)你的意思,可能到最后你說的會(huì)變得相當(dāng)令人費(fèi)解。RangeIterator是很長且怪異的,因?yàn)樗仨毑皇褂醚h(huán)語法來描述一個(gè)循環(huán)的功能。生成器是答案。

我們還能如何使用生成器作為迭代器的能力?

使對(duì)象可迭代。只要寫一個(gè)迭代器函數(shù)來一直調(diào)用this,在其出現(xiàn)的地方生成每一個(gè)值。然后以該對(duì)象的[Symbol.iterator]方法來安裝該生成器函數(shù)。

簡化數(shù)組構(gòu)建函數(shù)。實(shí)現(xiàn)一個(gè)函數(shù),每當(dāng)其被調(diào)用就會(huì)返回一個(gè)數(shù)組,如下面的這個(gè)例子:

// 將一維數(shù)組"icons"分為長度為"rowLength"的數(shù)組。

function splitIntoRows(icons, rowLength) {
  var rows = [];
  for (var i = 0; i < icons.length; i += rowLength) {
    rows.push(icons.slice(i, i + rowLength));
  }
  return rows;
}

生成器可以將代碼縮短很多:

function* splitIntoRows(icons, rowLength) {
  for (var i = 0; i < icons.length; i += rowLength) {
    yield icons.slice(i, i + rowLength);
  }
}

在行為上唯一的不同之處在于,取代一次性計(jì)算所有的結(jié)果,并返回他們的一個(gè)數(shù)組,這里返回一個(gè)迭代器且其可以按需一個(gè)一個(gè)地計(jì)算結(jié)果。

特別大量的結(jié)果。你不能構(gòu)建一個(gè)無窮大的數(shù)組。但是你可以返回一個(gè)生成器,其可以生成一個(gè)無限大的序列,同時(shí)每一個(gè)調(diào)用者都可以使用它不管他們需要多少個(gè)值。

重構(gòu)復(fù)雜的循環(huán)。你有龐大而丑陋的函數(shù)嗎?你是不是想將它分為兩個(gè)簡單的部分呢?生成器就是可以幫助你達(dá)成這一目標(biāo)的成套的重構(gòu)工具。當(dāng)你面對(duì)一個(gè)復(fù)雜的循環(huán),你可以將產(chǎn)生數(shù)據(jù)的代碼抽取出來編程一個(gè)獨(dú)立的生成器函數(shù)。然后改變循環(huán)為for循環(huán)(myNewGenerator(args)的var數(shù)據(jù))。

使用迭代的工具。ES6不提供擴(kuò)展的庫來進(jìn)行過濾,映射以及一般可以訪問任意可迭代的數(shù)據(jù)集。但生成器是偉大的,你只需要用幾行代碼就可以構(gòu)建你需要的工具。舉個(gè)例子說,假設(shè)你需要一個(gè)東西等同于Array.prototype.filter,其是在DOM NodeLists上工作的,不只是一個(gè)數(shù)組。這用代碼來實(shí)現(xiàn)就是小意思:

function* filter(test, iterable) {
  for (var item of iterable) {
    if (test(item))
      yield item;
  }
}

這個(gè)就是為什么生成器如此有用嗎?當(dāng)然。他們是要實(shí)現(xiàn)自定義的迭代器的簡單的方法。同時(shí),迭代器在整個(gè)ES6中是用于數(shù)據(jù)和循環(huán)的新標(biāo)準(zhǔn)。

但是,這還不是生成器能做的事情的全部。這甚至有可能不是他們做的最重要的事情。

生成器和異步代碼

這里是一個(gè) JS 代碼,我寫了一個(gè) while 的 back 部分。

        };
        })
      });
    });
  });
});

可能這看起來和你代碼的一部分比較相像。異步API通常情況下需要一個(gè)回調(diào),這就意味著你做一些事情時(shí)要寫一個(gè)額外的匿名函數(shù)。所以如果你有一部分代碼做三件事情,而不是三行代碼,你是在看三個(gè)縮進(jìn)層次的代碼。

這里有一些我已經(jīng)寫好的 JS 代碼:

}).on("close", function () {
  done(undefined, undefined);
}).on("error", function (error) {
  done(error);
});

異步API有錯(cuò)誤處理的約定,但不是使用異常。不同的API有不同的約定。在他們中的大多數(shù)中,錯(cuò)誤在默認(rèn)情況下被默默地刪除。其中有一些,即使是普通的圓滿完成,在默認(rèn)情況下都會(huì)被刪除。

直到現(xiàn)在,這些問題都只是簡單的轉(zhuǎn)畫為我們進(jìn)行異步編程的代價(jià)了。我們已經(jīng)開始接受異步代碼了,他們只是看起來不是像同步代碼那樣美好和簡單。

生成器提供了新的希望,可以不用這樣做的。

Q.async()是一個(gè)試驗(yàn)性的嘗試。其使用迭代器來生成類似于同步代碼的異步代碼。舉個(gè)例子:

// 
function makeNoise() {
  shake();
  rattle();
  roll();
}

// Asynchronous code to make some noise.
// Returns a Promise object that becomes resolved
// when we"re done making noise.
function makeNoise_async() {
  return Q.async(function* () {
    yield shake_async();
    yield rattle_async();
    yield roll_async();
  });
}

主要的區(qū)別在于,異步版本必須在每個(gè)需要調(diào)用異步函數(shù)的地方添加yield關(guān)鍵字。

在Q.async版本中添加一點(diǎn)小東西,如if語句或try/catch塊,與在普通同步版本中添加是完全相同的。相比于編寫異步代碼的其他方式,有種不是在學(xué)習(xí)一個(gè)全新的語言的感覺。

所以生成器指出了一個(gè)更適合人類大腦的新的異步編程模型。這項(xiàng)工作正在進(jìn)行中。除其他事項(xiàng)外,更好的語法可能有所幫助。

異步函數(shù)的提出,建立在雙方的承諾和生成器的基礎(chǔ)上,并從在C#類似的功能中采取靈感,這些都是ES7要做的事情。

我什么時(shí)候可以用這瘋狂的東西?

在服務(wù)器端,我們現(xiàn)在可以在io.js中使用 ES6 生成器。如果你啟用--harmony選項(xiàng),我們?cè)贜ode中可也已使用ES6生成器。

在瀏覽器中,現(xiàn)今只有火狐27版本以上以及谷歌瀏覽器39版本以上的支持ES6生成器。為了在現(xiàn)今的網(wǎng)絡(luò)上面使用生成器,你將需要使用Babel或者Traceur來將你的ES6的代碼翻譯為網(wǎng)絡(luò)友好的ES5代碼。

一些重要的事件值得了解

生成器是由布倫丹·艾希首次在JS上實(shí)現(xiàn)的。布倫丹·艾希的設(shè)計(jì)是緊緊跟隨由Icon啟發(fā)的Python生成器。他們?cè)缭?006年就運(yùn)用在火狐2.0版本上了。但是標(biāo)準(zhǔn)化的道路是崎嶇不平的,而且語法和行為在這個(gè)過程中改變了很多。ES6生成器是由編程黑客溫格安迪在火狐瀏覽器和谷歌瀏覽器中實(shí)現(xiàn)的。這項(xiàng)工作是由Bloomberg贊助的。

yield

關(guān)于生成器還有更多的說法。我們沒有包含.throw()和.return()方法,可選的參數(shù).next(),或yield*表達(dá)式語法。但我認(rèn)為這個(gè)帖子已經(jīng)很長了,且現(xiàn)在已經(jīng)足夠撲朔迷離了。像生成器本身,我們應(yīng)該停下來休息一下。

轉(zhuǎn)載:http://www.html-js.com

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79246.html

相關(guān)文章

  • ES6 走馬觀花(ECMAScript2015 新特性)

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

    wangzy2019 評(píng)論0 收藏0
  • ES6】迭代器與可迭代對(duì)象

    摘要:通過生成器創(chuàng)建的迭代器也是可迭代對(duì)象,因?yàn)樯善髂J(rèn)會(huì)為屬性賦值。我們可以用來訪問對(duì)象的默認(rèn)迭代器,例如對(duì)于一個(gè)數(shù)組獲得了數(shù)組這個(gè)可迭代對(duì)象的默認(rèn)迭代器,并操作它遍歷了數(shù)組中的元素。 ES6 新的數(shù)組方法、集合、for-of 循環(huán)、展開運(yùn)算符(...)甚至異步編程都依賴于迭代器(Iterator )實(shí)現(xiàn)。本文會(huì)詳解 ES6 的迭代器與生成器,并進(jìn)一步挖掘可迭代對(duì)象的內(nèi)部原理與使用方法 ...

    terasum 評(píng)論0 收藏0
  • ES6 的 for..of 和 Generator,從偽數(shù)組 jQuery 對(duì)象說起

    摘要:引用自可迭代對(duì)象和迭代器不以規(guī)矩,不成方圓為了使某個(gè)對(duì)象成為可迭代對(duì)象象,它必須實(shí)現(xiàn)方法,也就是說,它得有一個(gè)是的屬性。的遍歷,絕對(duì)應(yīng)該用。 pseudo 英 [sju:d??] 美 [su:do?]adj.假的,虛偽的n.[口]假冒的人,偽君子 pseudo-array 英 [sju:d???re?] 美 [sju:d???re?][計(jì)] 偽數(shù)組 jQuery 對(duì)象是偽數(shù)組 兩個(gè)...

    Harriet666 評(píng)論0 收藏0
  • ES6的常用語法

    摘要:和命令和類似于中的的使用都是用來聲明變量的,只是都存在各自的特殊用法。解構(gòu)數(shù)組和對(duì)象是中最常用也是最重要表示形式。實(shí)例生成以后,可以用方法分別指定狀態(tài)和狀態(tài)的回調(diào)函數(shù)。這個(gè)迭代器對(duì)象擁有一個(gè)叫做的方法來幫助你重啟函數(shù)并得到下一個(gè)值。 let和const命令 let和const類似于javascript中的var的使用,都是用來聲明變量的,只是都存在各自的特殊用法。 在javascrip...

    gougoujiang 評(píng)論0 收藏0
  • ES6-前世今生(0)

    摘要:更新了個(gè)版本,最新正式版是語言的下一代標(biāo)準(zhǔn),早已在年月正式發(fā)布。基本不支持移動(dòng)端瀏覽器對(duì)的支持情況版起便可以支持的新特性。比較通用的工具方案有,,,等。 1、ECMAScript是什么? 和 JavaScript 有著怎樣的關(guān)系? 1996 年 11 月,Netscape 創(chuàng)造了javascript并將其提交給了標(biāo)準(zhǔn)化組織 ECMA,次年,ECMA 發(fā)布 262 號(hào)標(biāo)準(zhǔn)文件(ECMA-...

    LeviDing 評(píng)論0 收藏0
  • webpack 項(xiàng)目構(gòu)建:(二)ES6 編譯環(huán)境搭建

    摘要:本質(zhì)就是一個(gè)編譯器,通過將源代碼解析成抽象語法樹將源代碼的結(jié)果一系列轉(zhuǎn)換生成目標(biāo)代碼的將目標(biāo)代碼的轉(zhuǎn)換成代碼。項(xiàng)目構(gòu)建三開發(fā)環(huán)境本地服務(wù)器搭建源碼下載地址參考資料入門阮一峰中文文檔中文網(wǎng) 注:以下教程均在 windows 環(huán)境實(shí)現(xiàn),使用其他操作系統(tǒng)的同學(xué)實(shí)踐過程可能會(huì)有些出入。 ??在上一章 webpack 項(xiàng)目構(gòu)建:(一)基本架構(gòu)搭建 我們搭建了一個(gè)最基本的 webpack 項(xiàng)目,現(xiàn)...

    marser 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<