基本概念函數
Generator
函數有多種理解角度。從語法上,首先能夠把它理解成,Generator
函數是一個狀態機,封裝了多個內部狀態。指針
執行Generator
函數會返回一個遍歷器對象,也就是說,Generator
函數除了狀態機,仍是一個遍歷器對象生成函數。返回的遍歷器對象,能夠依次遍歷Generator
函數內部的每個狀態。code
形式上,Generator
函數是一個普通函數,可是有兩個特徵。一是,function
命令與函數名之間有一個星號;二是,函數體內部使用yield
語句,定義不一樣的內部狀態(yield
語句在英語裏的意思就是「產出」)。對象
'use strict'; function * helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } let hw = helloWorldGenerator();
上面代碼定義了一個Generator
函數helloWorldGenerator
,它內部有兩個yield
語句「hello」
和「world」
,即該函數有三個狀態:hello
,world
和return
語句(結束執行)。遞歸
而後,Generator
函數的調用方法與普通函數同樣,也是在函數名後面加上一對圓括號。不一樣的是,調用Generator
函數後,該函數並不執行,返回的也不是函數運行結果,而是一個指向內部狀態的指針對象,遍歷器對象(Iterator Object
)。generator
調用遍歷器對象的next
方法,使得指針移向下一個狀態。也就是說,每次調用next
方法,內部指針就從函數頭部或上一次停下來的地方開始執行,直到遇到下一個yield
語句(或return
語句)爲止。換言之,Generator
函數是分段執行的,yield
語句是暫停執行的標記,而next
方法能夠恢復執行。io
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
方法。console
第一次調用,Generator
函數開始執行,直到遇到第一個yield
語句爲止。next
方法返回一個對象,它的value
屬性就是當前yield
語句的值hello
,done
屬性的值false
,表示遍歷尚未結束。function
第二次調用,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
方法,返回的都是這個值。
總結一下,調用Generator
函數,返回一個遍歷器對象,表明Generator
函數的內部指針。之後,每次調用遍歷器對象的next
方法,就會返回一個有着value
和done
兩個屬性的對象。value
屬性表示當前的內部狀態的值,是yield
語句後面那個表達式的值;done
屬性是一個布爾值,表示是否遍歷結束。
用來在一個Generator
函數裏面執行另外一個Generator
函數,咱們須要用yield*
語句。
若是yield
命令後面跟的是一個遍歷器對象,須要在yield
命令後面加上星號,代表它返回的是一個遍歷器對象。這被稱爲yield*
語句。
'use strict'; function *anotherGenerator(i) { yield i + 1; yield i + 2; yield i + 3; } function *generator(i) { yield i; yield *anotherGenerator(i); yield i + 10; } let gen = generator(10); console.log(gen.next().value);//10 console.log(gen.next().value);//11 console.log(gen.next().value);//12 console.log(gen.next().value);//13 console.log(gen.next().value);//20 console.log(gen.next().value);//undefined
運行結果就是使用一個遍歷器,遍歷了多個Generator
函數,有遞歸的效果。