摘要:從語法上,可以將函數(shù)理解為一個狀態(tài)機(jī),它封裝了多個內(nèi)部狀態(tài)。返回的遍歷器對象,可以依次遍歷函數(shù)內(nèi)部的每一個狀態(tài)。
基本概念 理解
Generator函數(shù)是ES 6提供的一種異步編程解決方案。從語法上,可以將Generator函數(shù)理解為一個狀態(tài)機(jī),它封裝了多個內(nèi)部狀態(tài)。執(zhí)行Generator函數(shù)會返回一個遍歷器對象,也就是說Generator函數(shù)除了是一個狀態(tài)機(jī),還是一個遍歷器對象生成函數(shù)。返回的遍歷器對象,可以依次遍歷Generator函數(shù)內(nèi)部的每一個狀態(tài)。
為什么使用Generator最大的好處就是函數(shù)可以被暫停執(zhí)行并保持上下文,這個運行方式在處理那些需要暫停的任務(wù)時非常有用,而被維持的上下文是為了在將來對運行環(huán)境進(jìn)行恢復(fù)。
語法 Generator函數(shù)Generator函數(shù)以function *申明開頭,并在需要暫停運行的地方添加yield關(guān)鍵字
function* myGenerator(){
// A
yield "foo"
// B
}
執(zhí)行上面的myGenerator方法會創(chuàng)建一個Generator對象,我們可以通過next方法來控制函數(shù)執(zhí)行。運行next方法會執(zhí)行myGenerator函數(shù)中的代碼,直到碰到下一個yield表達(dá)式(執(zhí)行完yield才暫停),此時yield后的表達(dá)式的值就被返回出去了,而且myGenerator的執(zhí)行就暫停了,當(dāng)我們再次運行next方法時,myGenerator會在上次暫停的地方接著向下運行。
const g = myGenerator()
const state01 = g.next() // {value: "foo", done: false}
const state02 = g.next() // {value: undefined, done: true}
yield
yield是伴隨著Generator函數(shù)出現(xiàn)的,它允許我們返回多個值(多個狀態(tài))。然而我們只能在Generator中才能使用它。如果我們嘗試在回調(diào)函數(shù)中用yield一個值,即使在Generator函數(shù)內(nèi)部聲明的,也會拋出錯誤
yield*yield*是用來在一個Generator函數(shù)內(nèi)部調(diào)用另一個Generator函數(shù)的
function* foo(){
yield "foo"
}
function* bar(){
yield "bar"
yield* foo()
yield "bar again"
}
const b = bar()
b.next() // {value: "bar", done: false}
b.next() // {value: "foo", done: false}
b.next() // {value: "bar again", done: false}
b.next() // {value: undefined, done: true}
遍歷
由于Generator方法會返回一個遍歷器對象(可遍歷對象),因此我們可以使用一個遍歷方法,例如for-of遍歷該對象內(nèi)部的所有狀態(tài)(值)
for-of遍歷
// 接上一個的例子
for (let e of bar()) {
console.log(e)
}
/* 依次輸出
bar
foo
bar again
*/
注意,b對應(yīng)的遍歷器對象已經(jīng)遍歷完畢,因此下面的例子只會輸出undefined
for (let e of b) {
console.log(e)
}
// undefined
解構(gòu)運算實現(xiàn)遍歷
console.log([...bar()]) // ["bar", "foo", "bar again"]return
我們可以在Generator函數(shù)中增加return語句
function* myGenerator(){
yield "foo"
yield "bar"
return "done"
}
var g = myGenerator()
g.next() // {value: "foo", done: false}
g.next() // {value: "bar", done: false}
g.next() // {value: "done", done: true}
g.next() // {value: undefined, done: true}
但是如果使用for-of或者解構(gòu)運算來遍歷遍歷器對象,則return后面的值將被忽略
for(let e of myGenerator()) {
console.log(e)
}
// foo
// bar
console.log([...myGenerator])
// ["foo", "bar"]
參考資料
ES6 Generator 探秘
ECMAScript 6 入門
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/87094.html
閱讀 3026·2021-10-14 09:43
閱讀 2985·2021-10-14 09:42
閱讀 4845·2021-09-22 15:56
閱讀 2431·2019-08-30 10:49
閱讀 1641·2019-08-26 13:34
閱讀 2436·2019-08-26 10:35
閱讀 658·2019-08-23 17:57
閱讀 2089·2019-08-23 17:15