1. 程式人生 > 其它 >生成器函式宣告與呼叫

生成器函式宣告與呼叫

生成器Generator

生成器本身是一個函式,是ES6 提供的一種非同步程式設計解決方案,語法行為與傳統函式完全不同

執行 Generator 函式會返回一個遍歷器物件,也就是說,Generator 函式除了狀態機,還是一個遍歷器物件生成函式。返回的遍歷器物件,可以依次遍歷 Generator 函式內部的每一個狀態。

function* fn() {
    console.log("hello world");
}

let iterator = fn();
// console.log(iterator); //Object [Generator] {}
// console.log(iterator.next()); // hello world { value: undefined, done: true }
iterator.next(); // hello world

形式上,Generator 函式是一個普通函式,但是有兩個特徵

-function關鍵字與函式名之間有一個星號;
-函式體內部使用yield表示式,定義不同的內部狀態(yield在英語裡的意思就是“產出”)。

yield表示式

yield可以看作是函式程式碼的分隔符。

由於 Generator 函式返回的遍歷器物件,只有呼叫next方法才會遍歷下一個內部狀態,所以其實提供了一種可以暫停執行的函式。yield表示式就是暫停標誌。

function* fn() {
    console.log(111);
    console.log(
222); console.log(333); console.log(444); } let iterator = fn(); iterator.next();
// 1111
// 2222
// 3333
// 4444

上面程式碼,在呼叫next方法後,遍歷指標會依次執行函式中的程式碼。

使用yield分隔符後,將函式中的程式碼分割成n個程式碼片段,可以通過依次呼叫next方法執行

function* fn() {
    console.log(111);
    yield '一隻沒有耳朵';
    console.log(222);
    yield '一隻沒有尾巴';
    console.log(
333); yield '真奇怪'; console.log(444); } let iterator = fn(); console.log(iterator.next()); // 111 console.log(iterator.next()); // 222 console.log(iterator.next()); // 333 console.log(iterator.next()); // 444 // 111 // { value: '一隻沒有耳朵', done: false } // 222 // { value: '一隻沒有尾巴', done: false } // 333 // { value: '真奇怪', done: false } // 444 // { value: undefined, done: true }

遍歷器物件的next方法的執行邏輯如下:

(1)遇到yield表示式,就暫停執行後面的操作,並將緊跟在yield後面的那個表示式的值,作為返回的物件的value屬性值。
(2)下一次呼叫next方法時,再繼續往下執行,直到遇到下一個yield表示式。
(3)如果沒有再遇到新的yield表示式,就一直執行到函式結束,直到return語句為止,並將return語句後面的表示式的值,作為返回的物件的value屬性值。
(4)如果該函式沒有return語句,則返回的物件的value屬性值為undefined。

yield表示式後面的表示式,只有當呼叫next方法、內部指標指向該語句時才會執行,因此等於為 JavaScript 提供了手動的“惰性求值”(Lazy Evaluation)的語法功能。

function* gen() {
    yield 123 + 456;
}

let iterator = gen();
console.log(iterator.next().value); // 579
console.log(iterator.next().value); // undefined

Generator 函式的呼叫方法與普通函式一樣,也是在函式名後面加上一對圓括號。不同的是,呼叫 Generator 函式後,該函式並不執行,返回的也不是函式執行結果,而是一個指向內部狀態的指標物件,也就是上一章介紹的遍歷器物件(Iterator Object)。

function* gen() {
    yield 123 + 456;
}

let iterator = gen();
console.log(iterator.next()); // { value: 579, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

下一步,必須呼叫遍歷器物件的next方法使得指標移向下一個狀態。也就是說,每次呼叫next方法,內部指標就從函式頭部或上一次停下來的地方開始執行,直到遇到下一個yield表示式(或return語句)為止。換言之,Generator 函式是分段執行的,yield表示式是暫停執行的標記,而next方法可以恢復執行

總結:

呼叫 Generator 函式,返回一個遍歷器物件,代表 Generator 函式的內部指標。以後,每次呼叫遍歷器物件的next方法,就會返回一個有著valuedone兩個屬性的物件。value屬性表示當前的內部狀態的值,是yield表示式後面那個表示式的值;done屬性是一個布林值,表示是否遍歷結束。

生成器Generator函式的引數傳遞

yield表示式後面的表示式,只有當呼叫next方法、內部指標指向該語句時才會執行,因此等於為 JavaScript 提供了手動的“惰性求值”(Lazy Evaluation)的語法功能。