文章出處

1、ES2017標準引入async函數,那么async函數到底是個什么函數呢?

async 是一個generator函數的語法糖。

2、那么generator函數到底是什么函數ne?

generator函數是ES6提供的一種異步編程解決方案,與傳統函數完全不同。

3、如何去理解generator函數呢?

從語法上,可以認為generator函數是一個狀態機,封裝了多個內部狀態。

從返回內容上,可以認為generator函數是一個遍歷器對象生成器,執行generator函數會返回一個遍歷器對象,可以通過next函數一次遍歷內部的每一個狀態。

從形式上,generator函數是一個普通函數,有兩個特征,(1)function關鍵字與函數之間有一個*號;(2)函數內部使用yield表達式,定義不同的內部狀態(yield)(yield意思是溢出)

4、舉個栗子

(1)上述函數,定義一個generator函數helloSuningGenerator,他的內部有兩個yield表達式(hello和suning),也就是說,該函數有三個狀態:hello,suning,return語句(結束執行)。調用generator函數和普通函數一樣,加(),但是generator函數并不執行,返回的是undefined。

(2)調用遍歷器對象使用next方法,使指針移向下一個狀態。也就是說,每次調用next方法,內部指針就從函數頭部或者上一次停下來的地方開始執行,遇到下一個yield表達式(或return語句)為止。yield表達式是暫停執行的標記,而next方法可以恢復執行。

上面代碼說明一共調用四次next方法。

第一次調用,generator函數開始執行,直到遇到第一個yield表達式為止。next方法返回一個對象,返回對象的value值就是當前yield表達式的值hello。done屬性值false,表示遍歷還沒有結束。

第二次調用,generator函數從上次yield表達式停下來地方,一直執行到下一個yield表達式。next方法返回對象的value屬性就是當前yield表達式的值world。done屬性值false,表示遍歷還沒有結束。

第三次調用,generator函數從上次yield表達式停下來的地方,一直執行到return語句(如果沒有return語句,就執行到函數結束)。next方法返回的對象的value值屬性,就是緊跟return與后邊的表達式的值。done屬性為true,以后調用next方法,done屬性都是這個值。

5、總結

調用generator函數,返回一個遍歷器對象,代表generator函數內部指針。以后,每一次調用遍歷器對象的next方法,就會返回一個有著value和done兩個屬性的對象。

value屬性表示當前內部狀態的值,是yield表達式后邊那個表達式的值;

done屬性是一個布爾值,表示遍歷時候結束。

------------------------------------------------

那么yield表達式是什么ne ?

yield表達式

由于generator函數返回的遍歷器對象,只有調用next方法才會遍歷下一個內部狀態,所以提供了一種可以暫停執行的函數。yield表達式就是暫停標志。

遍歷器對象的next方法的運行邏輯如下:

(1)遇到yield表達式,就暫停執行后邊的操作,并且將緊跟在yield后邊的那個表達式的值,作為返回的對象的value屬性值。

(2)下一次調用next方法,在之前暫停的地方繼續往下執行,知道遇到下一個yield表達式。

(3)如果沒有遇到新的yield的表達式,就一直運行到函數結束,直到return語句為止,并將return語句后邊的表達式的值作為返回對象的value屬性值。

(4)如果該函數沒有return語句,則返回對象的value屬性值為undefined。

注意:

yield表達式后邊的表達式,只有當調用next方法,內部指針指向該語句時才會執行。

1、舉個栗子

上面代碼中,23+78不會立即求值,只有在調用next方法將指針移到這一句時,才會求值。

2、yield表達式和return語句相同點和區別?

相同之處是:都能返回緊跟在語句后邊的那個表達式的值,作為返回對象的value屬性的值。

不同之處是:(1)每次遇到yield,函數停止執行,下一次再從這個位置繼續向后執行;而return語句不具備記憶功能。(2)一個函數中,只能執行一次(或者說一個)return語句,但是可以執行多次(多個)yield表達式,當時generator可以不用yield表達式,這樣可以貶稱一個暫緩執行的函數。

上面代碼中,f 如果是普通函數,在為gene賦值時才會執行。但是generator函數,變成只用調用next方法,函數f才會執行。

3、舉個栗子

上面代碼,yield必須在generator函數里面,不然會報錯。

4、舉個栗子

上面代碼會產生句法錯誤,因為forEach方法的參數是一個普通函數,但是在里面使用了yield表達式。

一種修改方法是改用for循環。

上面代碼還是顯示undefined。

5、舉個栗子

 

報錯

上面代碼顯示,沒有定義

上面代碼顯示,沒有定義

 6、舉個栗子

------------------------------------------------

那么next方法參數

yield表達式本身沒有返回值,或者說是undefined。next方法可以帶一個參數,該參數會被當成上一個yield表達式的返回值。

上面代碼先定義了一可以無限運行的generator函數f ,如果next方法沒有參數,每次運行到yield表達式,變量reset的值總是undefined。當帶一個參數true,變量reset就被重置為這個參數。

generator函數從暫停狀態到恢復狀態運行,他的上下文(context)是不變的。通過next方法的參數,就可以實現generator函數運行的不同階段,從外部向內部注入不同的值,從而調整函數行為。

舉個栗子

上面代碼中,第一次運行后,5+1=6;第二次運行next方法不帶參數,y的值為2*undefined,除以3還是NAN,因此返回的對象的value值也是NAN。第三次運行next方法不帶參數,z也是undefined,返回的對象的value屬性等于5+NAN+undefined,即NAN。

緊接著執行

上面代碼,第一次調用next方法,返回x+1=6;第二次調用next方法,上一次yield表達式的值設12,因此y=24;返回y/3=8;第三次調用next方法,將上一次yield表達式的值設為13,因此找3,這時候新,于4,所以return語句的值=42。

注意:next方法的參數表示上一個yield表達式的返回值,所以第一次使用next方法時,傳遞參數是無效的。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()