摘要:返回的遍歷器對象,可以依次遍歷函數內部的每一個狀態。下一步,必須調用遍歷器對象的方法,使得指針移向下一個狀態。從語義上講,第一個方法用來啟動遍歷器對象,所以不用帶有參數。
Generator理解
Generator 函數是 ES6 提供的一種異步編程解決方案,可以這么理解:
從語法上,首先可以把它理解成,Generator 函數是一個狀態機,封裝了多個內部狀態。
執行 Generator 函數會返回一個遍歷器對象,也就是說,Generator 函數除了狀態機,還是一個遍歷器對象生成函數。返回的遍歷器對象,可以依次遍歷 Generator 函數內部的每一個狀態。
形式上,Generator 函數是一個普通函數,但是有兩個特征。一是,function關鍵字與函數名之間有一個星號;二是,函數體內部使用yield表達式,定義不同的內部狀態(yield在英語里的意思就是“產出”)。
function* helloWorldGenerator() { yield "hello"; yield "world"; return "ending"; } var hw = helloWorldGenerator();
Generator 函數的調用方法與普通函數一樣,也是在函數名后面加上一對圓括號。不同的是,調用 Generator 函數后,該函數并不執行,返回的也不是函數運行結果,而是一個指向內部狀態的指針對象,也就是上一章介紹的遍歷器對象(Iterator Object)。
下一步,必須調用遍歷器對象的next方法,使得指針移向下一個狀態。也就是說,每次調用next方法,內部指針就從函數頭部或上一次停下來的地方開始執行,直到遇到下一個yield表達式(或return語句)為止。換言之,Generator 函數是分段執行的,yield表達式是暫停執行的標記,而next方法可以恢復執行。
hw.next() // { value: "hello", done: false } hw.next() // { value: "world", done: false } hw.next() // { value: "ending", done: true } hw.next() // { value: undefined, done: true }
上面的程序執行了四次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語句后面的表達式的值(如果沒有return語句,則value屬性的值為undefined),done屬性的值true,表示遍歷已經結束。
第四次調用,此時 Generator 函數已經運行完畢,next方法返回對象的value屬性為undefined,done屬性為true。以后再調用next方法,返回的都是這個值。
yield認識由于 Generator 函數返回的遍歷器對象,只有調用next方法才會遍歷下一個內部狀態,所以其實提供了一種可以暫停執行的函數。yield表達式就是暫停標志。
(1)遇到yield表達式,就暫停執行后面的操作,并將緊跟在yield后面的那個表達式的值,作為返回的對象的value屬性值。
(2)下一次調用next方法時,再繼續往下執行,直到遇到下一個yield表達式。
(3)如果沒有再遇到新的yield表達式,就一直運行到函數結束,直到return語句為止,并將return語句后面的表達式的值,作為返回的對象的value屬性值。
(4)如果該函數沒有return語句或者執行完return之后再運行next的時候,則返回的對象的value屬性值為undefined,done為true。
需要注意,yield表達式只能用在 Generator 函數里面,用在其他地方都會報錯。
yield表達式如果用在另一個表達式之中,必須放在圓括號里面
yield表達式用作函數參數或放在賦值表達式的右邊,可以不加括號。
yield放在表達式中的時候,let s =(yield 1+2),s其值將會是undefined,而1+2這個等于3的值將會作為next返回對象的value的值
yield表達式本身沒有返回值,或者說總是返回undefined。next方法可以帶一個參數,該參數就會被當作上一個yield表達式的返回值。
這個參數就是解決了上面說的注意事項的最后一個,yield的返回值總是undefined,
由于next方法的參數表示上一個yield表達式的返回值,所以在第一次使用next方法時,傳遞參數是無效的。V8 引擎直接忽略第一次使用next方法時的參數,只有從第二次使用next方法開始,參數才是有效的。從語義上講,第一個next方法用來啟動遍歷器對象,所以不用帶有參數。
yield* 表達式如果在 Generator 函數內部,調用另一個 Generator 函數,默認情況下是沒有效果的。
這個就需要用到yield*表達式,用來在一個 Generator 函數里面執行另一個 Generator 函數。
function* inner() { yield "hello!"; } function* outer1() { yield "open"; yield inner(); yield "close"; } var gen = outer1() gen.next().value // "open" gen.next().value // 返回一個遍歷器對象 gen.next().value // "close" function* outer2() { yield "open" yield* inner() yield "close" } var gen = outer2() gen.next().value // "open" gen.next().value // "hello!" gen.next().value // "close"
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88924.html
摘要:是處理異步編程的一種方式,來看看和有什么不同或獲取值再來看看函數,函數前面是一個然后是函數名,函數體里面是用代表但是可以返回多次使用即不處理后面的返回的是一個對象的寫法更像是同步的語句,比更簡潔獲取值的幾種方式調用可以使用獲取值表示為最后一 Generator 是es6處理異步編程的一種方式,來看看和promise有什么不同 const myFirstPromise = new Pro...
摘要:調用棧被清空,消息隊列中并無任務,線程停止,事件循環結束。不確定的時間點請求返回,將設定好的回調函數放入消息隊列。調用棧執行完畢執行消息隊列任務。請求并發回調函數執行順序無法確定。 異步編程 JavaScript中異步編程問題可以說是基礎中的重點,也是比較難理解的地方。首先要弄懂的是什么叫異步? 我們的代碼在執行的時候是從上到下按順序執行,一段代碼執行了之后才會執行下一段代碼,這種方式...
摘要:異步過程控制了解異步的意義之后,我們來對比目前主流幾種異步過程控制方法,探討一下異步編程的最佳實踐。結語希望本文對大家有點幫助,能更深刻的理解異步編程,能寫出更優雅更高效的代碼。 同步和異步(Synchronous and Asynchronous) 了解javascript的同學想必對同步和異步的概念應該都很熟悉了,如果還有不熟悉的同學,我這里舉個形象的例子,比如我們早上起床后要干三...
摘要:調用函數后和普通函數不同的是,該函數并不立即執行,也不返回函數執行結果,而是返回一個指向內部狀態的對象,也可以看作是一個遍歷器對象。第一個只是用來啟動函數內部的遍歷器,傳參也沒有多大意義。 之前斷斷續續接觸到了一些ES6的知識,異步編程方面聽得比較多的就是Promise,直到最近比較系統地學習了ES6的新特性才發現Generator這個神奇的存在,它可以實現一些前所未有的事情,讓我頓時...
摘要:序在中,大家討論的最多的就是異步編程的操作,如何避免回調的多次嵌套。今天所講的和就是和異步編程有關,可以幫助我們把異步編程同步化。然而這樣的方法依然需要依賴外在的庫函數,于是中提出了和關鍵字。 序 在Javascript中,大家討論的最多的就是異步編程的操作,如何避免回調的多次嵌套。異步操作的回調一旦嵌套很多,不僅代碼會變的臃腫,還很容易出錯。各種各樣的異步編程解決方案也被不斷提出,例...
閱讀 2950·2021-11-23 09:51
閱讀 3776·2021-11-22 15:29
閱讀 3226·2021-10-08 10:05
閱讀 1552·2021-09-22 15:20
閱讀 952·2019-08-30 15:56
閱讀 1069·2019-08-30 15:54
閱讀 733·2019-08-26 11:54
閱讀 2636·2019-08-26 11:32