Our volunteers haven't translated this article into Türkçe yet. Join us and help get the job done!
You can also read the article in English (US).
The function*
declaration (function
keyword followed by an asterisk) defines a generator function, which returns a Generator
object.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
You can also define generator functions using the GeneratorFunction
constructor, or the function expression syntax.
Syntax
function* name([param[, param[, ... param]]]) { statements }
name
- The function name.
param
- The name of a formal parameter for the function.
statements
- The statements comprising the body of the function.
Description
Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.
Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous programming as they mitigate -- if not entirely eliminate -- the problems with callbacks, such as Callback Hell and Inversion of Control.
This pattern is what async
functions are built on top of.
Calling a generator function does not execute its body immediately; an iterator object for the function is returned instead. When the iterator's next()
method is called, the generator function's body is executed until the first yield
expression, which specifies the value to be returned from the iterator or, with yield*
, delegates to another generator function. The next()
method returns an object with a value
property containing the yielded value and a done
property which indicates whether the generator has yielded its last value, as a boolean. Calling the next()
method with an argument will resume the generator function execution, replacing the yield
expression where execution was paused with the argument from next()
.
A return
statement in a generator, when executed, will make the generator finished (i.e the done
property of the object returned by it will be set to true
). If a value is returned, it will be set as the value
property of the object returned by the generator.
Much like a return
statement, an error thrown inside the generator will make the generator finished -- unless caught within the generator's body.
When a generator is finished, subsequent next
calls will not execute any of that generator's code, they will just return an object of this form: {value: undefined, done: true}
.
Examples
Simple example
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 // ...
Example with yield*
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
Passing arguments into Generators
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
Return statement in a generator
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 }
Generators are not constructable
function* f() {} var obj = new f; // throws "TypeError: f is not a constructor
Generator defined in an expression
const foo = function* () { yield 10; yield 20; }; const bar = foo(); console.log(bar.next()); // {value: 10, done: false}
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'function*' in that specification. |
Standard | Initial definition. |
ECMAScript 2016 (ECMA-262) The definition of 'function*' in that specification. |
Standard | Changed that generators should not have [[Construct]] trap and will throw when used with new . |
ECMAScript Latest Draft (ECMA-262) The definition of 'function*' in that specification. |
Draft |
Browser compatibility
Desktop | Mobile | Server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Basic support | Chrome Full support 39 | Edge Full support 13 | Firefox Full support 26 | IE No support No | Opera Full support 26 | Safari Full support 10 | WebView Android Full support Yes | Chrome Android Full support 39 | Edge Mobile Full support Yes | Firefox Android Full support 26 | Opera Android Full support Yes | Safari iOS Full support 10 | Samsung Internet Android Full support 4.0 | nodejs
Full support
4.0.0
|
IteratorResult object instead of throwing | Chrome Full support 49 | Edge Full support 13 | Firefox Full support 29 | IE No support No | Opera Full support Yes | Safari Full support Yes | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile Full support Yes | Firefox Android Full support 29 | Opera Android Full support Yes | Safari iOS Full support Yes | Samsung Internet Android Full support Yes | nodejs Full support Yes |
Not constructable with new (ES2016) | Chrome Full support Yes | Edge ? | Firefox Full support 43 | IE No support No | Opera Full support Yes | Safari Full support 10 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 43 | Opera Android Full support Yes | Safari iOS Full support 10 | Samsung Internet Android Full support Yes | nodejs Full support Yes |
Trailing comma in parameters | Chrome ? | Edge ? | Firefox Full support 52 | IE ? | Opera Full support Yes | Safari ? | WebView Android ? | Chrome Android ? | Edge Mobile ? | Firefox Android Full support 52 | Opera Android ? | Safari iOS ? | Samsung Internet Android ? | nodejs Full support 8.0.0 |
Legend
- Full support
- Full support
- No support
- No support
- Compatibility unknown
- Compatibility unknown
- User must explicitly enable this feature.
- User must explicitly enable this feature.
Firefox-specific notes
Generators and iterators in Firefox versions before 26
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 throwing
Starting with Gecko 29 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26), the completed generator function no longer throws a TypeError
"generator has already finished". Instead, it returns an IteratorResult
object like { value: undefined, done: true }
(bug 958951).
See also
function* expression
GeneratorFunction
object- Iteration protocols
yield
yield*
Function
objectfunction declaration
function expression
Functions and function scope
- Other web resources:
- Regenerator an ES2015 generator compiler to ES5
- Forbes Lindesay: Promises and Generators: control flow utopia -- JSConf EU 2013
- Task.js
- Iterating generators asynchronously