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方法時,傳遞參數是無效的。
文章列表
留言列表