生成器函式宣告與呼叫
生成器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
方法,就會返回一個有著value
和done
兩個屬性的物件。value
屬性表示當前的內部狀態的值,是yield
表示式後面那個表示式的值;done
屬性是一個布林值,表示是否遍歷結束。
生成器Generator函式的引數傳遞
yield
表示式後面的表示式,只有當呼叫next
方法、內部指標指向該語句時才會執行,因此等於為 JavaScript 提供了手動的“惰性求值”(Lazy Evaluation)的語法功能。