--- title: function* slug: Web/JavaScript/Reference/Statements/function* tags: - ECMAScript 2015 - Function - Iterator - JavaScript - Statement translation_of: Web/JavaScript/Reference/Statements/function* ---
function*
宣告式(function
關鍵字後面跟著一個星號)定義了一個生成器函式(generator function),他會回傳一個{{jsxref("Global_Objects/Generator","生成器(Generator)")}}物件。
你可以透過 {{jsxref("GeneratorFunction")}} 建構式來定義生成器函式。
function* name([param[, param[, ... param]]]) { statements }
name
param
statements
生成器是可以離開後再次進入的函式。在兩次進入之間,生成器的執行狀態(變數綁定狀態)會被儲存。
呼叫生成器函式並不會讓裡面的程式碼立即執行,而是會回傳一個針對該函式的迭代器(iterator)物件。當呼叫迭代器的 next()
方法時,生成器函式將會執行到遭遇的第一個 {{jsxref("Operators/yield", "yield")}} 運算式,該運算式給定的值將從迭代器中回傳,如果是 {{jsxref("Operators/yield*", "yield*")}} 則會交給另一個生成器函式處理。next()
方法回傳一個物件,該物件有 value
屬性,包含了產生的數值,還有 done
屬性,為布林值,指出該生成器是否產出最後的數值。呼叫 next()
方法如果帶有一個參數,將會讓先前暫停的生成器函式恢復執行,以該參數值取代先前暫停的 yield
陳述式。
生成器中的 return
陳述式被執行時,會讓生成器 done
狀態為真。若有數值被返回的動作帶回,將是放在 value
傳回的。已返回的生成器不會再產生任何數值。
function* idMaker() { var index = 0; while (index < index+1) yield index++; } var gen = idMaker(); console.log(gen.next().value); // 0 console.log(gen.next().value); // 1 console.log(gen.next().value); // 2 console.log(gen.next().value); // 3 // ...
function* anotherGenerator(i) { yield i + 1; yield i + 2; yield i + 3; } function* generator(i) { yield i; yield* anotherGenerator(i); yield i + 10; } var 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
function* logGenerator() { console.log(0); console.log(1, yield); console.log(2, yield); console.log(3, yield); } var gen = logGenerator(); // the first call of next executes from the start of the function // until the first yield statement gen.next(); // 0 gen.next('pretzel'); // 1 pretzel gen.next('california'); // 2 california gen.next('mayonnaise'); // 3 mayonnaise
function* yieldAndReturn() { yield "Y"; return "R"; yield "unreachable"; } var gen = yieldAndReturn() console.log(gen.next()); // { value: "Y", done: false } console.log(gen.next()); // { value: "R", done: true } console.log(gen.next()); // { value: undefined, done: true }
function* f() {} var obj = new f; // throws "TypeError: f is not a constructor"
const foo = function* () { yield 10; yield 20; };
const bar = foo();console.log(bar.next()); // {value: 10, done: false}
Specification | Status | Comment |
---|---|---|
{{SpecName('ES2015', '#', 'function*')}} | {{Spec2('ES2015')}} | Initial definition. |
{{SpecName('ES2016', '#', 'function*')}} | {{Spec2('ES2016')}} | Changed that generators should not have [[Construct]] trap and will throw when used with new . |
{{SpecName('ESDraft', '#', 'function*')}} | {{Spec2('ESDraft')}} |
{{Compat("javascript.statements.generator_function")}}
Older Firefox versions implement an older version of the generators proposal. In the older version, generators were defined using a regular function
keyword (without an asterisk) among other differences. See Legacy generator function for further information.
IteratorResult
object returned instead of throwingStarting with Gecko 29 {{geckoRelease(29)}}, the completed generator function no longer throws a {{jsxref("TypeError")}} "generator has already finished". Instead, it returns an IteratorResult
object like { value: undefined, done: true }
({{bug(958951)}}).