--- 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
}
nameparamstatements生成器是可以離開後再次進入的函式。在兩次進入之間,生成器的執行狀態(變數綁定狀態)會被儲存。
呼叫生成器函式並不會讓裡面的程式碼立即執行,而是會回傳一個針對該函式的迭代器(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)}}).