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

資訊專欄INFORMATION COLUMN

ES6學(xué)習(xí)筆記之Generator函數(shù)

cjie / 1780人閱讀

摘要:調(diào)用函數(shù)后和普通函數(shù)不同的是,該函數(shù)并不立即執(zhí)行,也不返回函數(shù)執(zhí)行結(jié)果,而是返回一個指向內(nèi)部狀態(tài)的對象,也可以看作是一個遍歷器對象。第一個只是用來啟動函數(shù)內(nèi)部的遍歷器,傳參也沒有多大意義。

之前斷斷續(xù)續(xù)接觸到了一些ES6的知識,異步編程方面聽得比較多的就是Promise,直到最近比較系統(tǒng)地學(xué)習(xí)了ES6的新特性才發(fā)現(xiàn)Generator這個神奇的存在,它可以實現(xiàn)一些前所未有的事情,讓我頓時對它充滿了興趣。

為什么需要Generator?

JavaScript異步編程是為解決JavaScript執(zhí)行環(huán)境是“單線程”這個問題的。在JavaScript中,異步編程的使用非常頻繁,也經(jīng)常會出現(xiàn)需要逐步完成多個異步操作的情況。之前用回調(diào)函數(shù)實現(xiàn)異步編程如果碰到了這種問題就需要嵌套使用回調(diào)函數(shù),異步操作越多,嵌套得就越深,這樣非常不利于代碼的維護,代碼閱讀起來也很困難。Generator函數(shù)是ES6提出的一種異步編程解決方案,它可以避免回調(diào)的嵌套,但是它的用處可不僅僅如此哦,待我細(xì)細(xì)道來。

舉個小例子
function* gen1() {
    yield 1;
    yield "hello";
    return true;
}
let g1 = gen1();
g1.next();  // Object {value: 1, done: false}
g1.next();  // Object {value: "hello", done: false}
g1.next();  // Object {value: true, done: true}
g1.next();  // Object {value: undefined, done: true}

上面的代碼就定義了一個Generator函數(shù),Generator函數(shù)的定義跟普通函數(shù)差不多,只是在function關(guān)鍵字后面加了一個星號。調(diào)用Generator函數(shù)后和普通函數(shù)不同的是,該函數(shù)并不立即執(zhí)行,也不返回函數(shù)執(zhí)行結(jié)果,而是返回一個指向內(nèi)部狀態(tài)的generator對象,也可以看作是一個遍歷器對象。然后必須調(diào)用該對象的next方法,讓函數(shù)繼續(xù)走下去,是指針移向下一個狀態(tài)。每當(dāng)碰到y(tǒng)ield語句,內(nèi)部指針就停下來,直到下一次調(diào)用next()才開始執(zhí)行。
上面代碼調(diào)用了四次next方法,遍歷才結(jié)束。next方法會返回一個有兩個屬性的對象,value屬性的值為當(dāng)前yield語句的值,done屬性的值表示遍歷是否結(jié)束,即最后一次調(diào)用next方法時,再也碰不到y(tǒng)ield或者return語句了。
星號寫在哪
function關(guān)鍵字和函數(shù)名之間的星號寫在哪都可以,只要在兩者之間即可,但是一般都采取我上面代碼的那種寫法。

Generator函數(shù)本質(zhì)

上面說了那么多,想必大家已經(jīng)知道Generator函數(shù)是怎么用的了,那么Generator本質(zhì)上到底是個啥呢?Generator函數(shù)的理解有多種:

Generator函數(shù)可以被理解成一個狀態(tài)機,里面封裝了多種狀態(tài),有興趣的同學(xué)可以去了解一下狀態(tài)機,操作系統(tǒng)的書里都會講到。

Generator函數(shù)還可以被理解成一個遍歷器對象生成器,它返回的遍歷器對象可以依次遍歷Generator函數(shù)內(nèi)部的每一個狀態(tài)。這就是為什么之前說Generator函數(shù)不僅是為了解決回調(diào)函數(shù)嵌套問題。Generator函數(shù)是生成一個對象,但是調(diào)用的時候前面不能加new命令。

yield語句

yield語句是Generator函數(shù)內(nèi)部可以暫停執(zhí)行程序的語句,yield語句后面的值可以是各種數(shù)據(jù)類型,字符串,整數(shù),布爾值等等都可以。這里主要想說說Generator函數(shù)中yield語句和return語句的區(qū)別。

和return語句區(qū)別

從上面的例子可以看出,函數(shù)不僅是碰到y(tǒng)ield語句才會停止執(zhí)行,碰到return語句也會停止執(zhí)行。這很容易理解,不管怎樣Generator函數(shù)也是一個函數(shù),碰到return語句必然會停止執(zhí)行,返回值。那么,兩者的區(qū)別是什么呢?先來看個例子:

function* gen2() {
    return true;
    yield 1;
    yield "hello";
}
let g2 = gen2();
g2.next();  // Object {value: true, done: true}
g2.next();  // Object {value: undefined, done: true}

從上面例子可以看出,當(dāng)碰到return語句時,返回對象的done屬性值就為true,遍歷結(jié)束,不管后面是否還有yield或者return語句。這種區(qū)別本質(zhì)上是因為yield語句具備位置記憶功能而return語句則沒有該功能。

再說一點

Generator函數(shù),不管內(nèi)部有沒有yield語句,調(diào)用函數(shù)時都不會執(zhí)行任何語句,只有當(dāng)調(diào)用next(),內(nèi)部語句才會執(zhí)行,只要調(diào)用next(),就會返回一個對象。yield語句只是函數(shù)暫停執(zhí)行的一個標(biāo)記。

function* gen3() {
    console.log("執(zhí)行了么?");
}
let g3 = gen3();  // 沒有任何輸出
g3.next();
// 執(zhí)行了么?
// Object {value: undefined, done: true}

注意:yield函數(shù)不能在普通函數(shù)中使用,否則會報錯。

next方法

除了yield語句,next方法也是Generator函數(shù)實現(xiàn)中很重要的特性。既然next()是一個函數(shù),那么這個函數(shù)可以帶參數(shù)么,當(dāng)然可以。上面的例子比較簡單,都只是一些單純的yield語句,其實Generator函數(shù)和普通函數(shù)一樣里面是可以進行各種復(fù)雜的計算和操作的,也可以有各種循環(huán)語句,不僅next方法可以傳參數(shù),Generator函數(shù)也是可以傳參數(shù)的,立馬上例子:

function* gen4(a) {
    let b = yield (a + 1);
    return b * 2;
}
let g4 = gen4(1);
g4.next();  //  Object {value: 2, done: false}
g4.next();  //  Object {value: NaN, done: true}
let g5 = gen4(1);
g5.next();  //  Object {value: 2, done: false}
g5.next(3);  //  Object {value: 6, done: true}

上面例子中,Generator函數(shù)需要接收一個參數(shù)a,表面上變量b是用yield語句賦值了,但是遺憾的是這個賦值好像并沒有成功,當(dāng)?shù)诙握{(diào)用next方法(沒有傳參數(shù))時,返回的對象value值居然為NaN,而不是我們想的 2 *(1+1)= 4。但是如果第二次調(diào)用next方法時,傳入一個參數(shù)3,返回對象的value值就為6。這可以說明兩點:

yield語句沒有返回值,或者總是返回undefined;

next方法如果帶上一個參數(shù),這個參數(shù)就是作為上一個yield語句的返回值。

注意:因為next方法表示上一個yield語句的返回值,所以必須有上一個yield語句的存在,那么第一次調(diào)用next方法時就不能傳參數(shù)。第一個next只是用來啟動Generator函數(shù)內(nèi)部的遍歷器,傳參也沒有多大意義。

再說Generator函數(shù)與普通函數(shù)區(qū)別 可以用prototype么?

雖然Generator函數(shù)和普通函數(shù)區(qū)別很大,但是Generator函數(shù)的實例也可以繼承Generator函數(shù)的prototype對象上的方法。

function* gen5() {}
gen5.prototype.say = function() {
    console.log("有g(shù)enerator?");
}
let g6 = gen5();
g6.say();  // 有g(shù)enerator?

從上面代碼可以看出,Generator函數(shù)返回的g6,繼承了gen5.prototype。

this咋用?

大家都知道普通函數(shù)都會有一個this對象,那么Generator的this對象怎么用呢?還是例子更直觀:

function* gen6() {
    this.a = 1;
}
let g7 = gen6();
g7.a;  //  undefined

上面代碼中,Generator函數(shù)在this對象上添加了一個屬性a,g7實例并不能取到這個屬性。那么怎么讓Generator函數(shù)返回一個可以正常使用this對象的實例呢?阮一峰老師提供了一種方法,首先,生成一個空對象,使用call方法綁定Generator函數(shù)內(nèi)部的this。這樣,構(gòu)造函數(shù)調(diào)用以后,這個空對象就是Generator函數(shù)的實例對象了。參考代碼在這:http://es6.ruanyifeng.com/#docs/generator

Generator函數(shù)與Iterator

Generator函數(shù)返回的是一個遍歷器對象,那么它在遍歷這方面肯定有用武之地,下一次討論Iterator時候再總結(jié)吧。

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

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

相關(guān)文章

  • JS筆記

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細(xì)介紹 HTT...

    rottengeek 評論0 收藏0
  • JavaScript異步編程解決方案筆記

    摘要:異步編程解決方案筆記最近讀了樸靈老師的深入淺出中異步編程一章,并參考了一些有趣的文章。另外回調(diào)函數(shù)中的也失去了意義,這會使我們的程序必須依賴于副作用。 JavaScript 異步編程解決方案筆記 最近讀了樸靈老師的《深入淺出NodeJS》中《異步編程》一章,并參考了一些有趣的文章。在此做個筆記,記錄并鞏固學(xué)到的知識。 JavaScript異步編程的兩個核心難點 異步I/O、事件驅(qū)動使得...

    dmlllll 評論0 收藏0
  • JavaScript學(xué)習(xí)筆記第二天_函數(shù)

    摘要:廖雪峰的教程學(xué)習(xí)筆記變量作用域不能聲明塊級的變量,的函數(shù)內(nèi)變量聲明會被提升至函數(shù)體開頭則用來解決這個塊級變量聲明,于引入。普通函數(shù)一般將賦值為。高階函數(shù)輸出結(jié)果是。箭頭函數(shù)新引入的相當(dāng)于如下的匿名函數(shù)其中為參數(shù)。 廖雪峰的JavaScript教程學(xué)習(xí)筆記 1. 變量作用域 var 不能聲明塊級的變量,js的函數(shù)內(nèi)變量聲明會被提升至函數(shù)體開頭let 則用來解決這個塊級變量聲明,于ES6...

    ShevaKuilin 評論0 收藏0
  • ES6學(xué)習(xí)筆記3-Set和Map、Promise、Iterator、Generator、async

    摘要:去除數(shù)組的重復(fù)成員這表明,在內(nèi)部,兩個是相等。返回一個布爾值,表示該值是否為的成員。使用回調(diào)函數(shù)遍歷每個成員沒有返回值。對象特點對象有三種狀態(tài)進行中已完成,又稱和已失敗。方法是的別名,用于指定發(fā)生錯誤時的回調(diào)函數(shù)。 Set和Map數(shù)據(jù)結(jié)構(gòu) Set 新的數(shù)據(jù)結(jié)構(gòu)Set類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。Set 本身是一個構(gòu)造函數(shù),用來生成 Set 數(shù)據(jù)結(jié)構(gòu)。接受一個數(shù)組(或...

    sevi_stuo 評論0 收藏0
  • ES6筆記 變量解構(gòu)賦值

    摘要:變量的解構(gòu)賦值中允許按照一定模式,從數(shù)組和對象中提取,對變量進行賦值。數(shù)組的解構(gòu)賦值上面的代碼標(biāo)示可以從數(shù)組中提取值,按照位置的對應(yīng)關(guān)系對變量進行賦值。默認(rèn)值解構(gòu)賦值允許指定默認(rèn)值。 變量的解構(gòu)賦值 ES6中允許按照一定模式,從數(shù)組和對象中提取,對變量進行賦值。 數(shù)組的解構(gòu)賦值 var [a,b,c] = [1,2,3]; a // 1; b // 2; c // 3; 上面的代碼標(biāo)示...

    baukh789 評論0 收藏0

發(fā)表評論

0條評論

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