Node v4 - Generator函數

一、Generator簡介

基本概念函數

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」,即該函數有三個狀態:helloworldreturn語句(結束執行)。遞歸

而後,Generator函數的調用方法與普通函數同樣,也是在函數名後面加上一對圓括號。不一樣的是,調用Generator函數後,該函數並不執行,返回的也不是函數運行結果,而是一個指向內部狀態的指針對象,遍歷器對象(Iterator Object)。generator

二、next方法

調用遍歷器對象的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語句的值hellodone屬性的值false,表示遍歷尚未結束。function

第二次調用,Generator函數從上次yield語句停下的地方,一直執行到下一個yield語句。next方法返回的對象的value屬性就是當前yield語句的值worlddone屬性的值false,表示遍歷尚未結束。遍歷

第三次調用,Generator函數從上次yield語句停下的地方,一直執行到return語句(若是沒有return語句,就執行到函數結束)。next方法返回的對象的value屬性,就是緊跟在return語句後面的表達式的值(若是沒有return語句,則value屬性的值爲undefined),done屬性的值true,表示遍歷已經結束。

第四次調用,此時Generator函數已經運行完畢,next方法返回對象的value屬性爲undefineddone屬性爲true。之後再調用next方法,返回的都是這個值。

總結一下,調用Generator函數,返回一個遍歷器對象,表明Generator函數的內部指針。之後,每次調用遍歷器對象的next方法,就會返回一個有着valuedone兩個屬性的對象。value屬性表示當前的內部狀態的值,是yield語句後面那個表達式的值;done屬性是一個布爾值,表示是否遍歷結束。

三、yield*語句

用來在一個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函數,有遞歸的效果。

相關文章
相關標籤/搜索