function*

The function* declaration (function keyword followed by an asterisk) defines a generator function, which returns a Generator object.

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 Optional
The name of a formal parameter for the function.
statements
The statements comprising the body of the function.

Description

Generators are functions that 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. However, an even simpler solution to these problems can be achieved with async functions.

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 an execution was paused with the argument from next().

A return statement in a generator, when executed, will make the generator finish (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 is 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 (true)
    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 }

Generator as an object property

const someObj = {
  *generator () {
    yield 'a';
    yield 'b';
  }
}

const gen = someObj.generator()

console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: undefined, done: true }

Generator as an object method

class Foo {
  *generator () {
    yield 1;
    yield 2;
    yield 3;
  }
}

const f = new Foo ();
const gen = f.generator();

console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }

Generator as a computed property

class Foo {
  *[Symbol.iterator] () {
    yield 1;
    yield 2;
  }
}

const SomeObj = {
  *[Symbol.iterator] () {
    yield 'a';
    yield 'b';
  }
}

console.log(Array.from(new Foo)); // [ 1, 2 ]
console.log(Array.from(SomeObj)); // [ 'a', 'b' ]

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}

Generator example

function* powers(n){
     //endless loop to generate
     for(let current =n;; current *= n){
         yield current;
     }
}

for(let power of powers(2)){
     //controlling generator
     if(power > 32) break;
     console.log(power)
           //2
          //4
         //8
        //16
       //32
}

Specifications

Specification
ECMAScript (ECMA-262)
The definition of 'function*' in that specification.

Browser compatibility

DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
function*Chrome Full support 39Edge Full support 13Firefox Full support 26IE No support NoOpera Full support 26Safari Full support 10WebView Android Full support 39Chrome Android Full support 39Firefox Android Full support 26Opera Android Full support 26Safari iOS Full support 10Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Full support 4.0.0
Full support 0.12
Disabled
Disabled From version 0.12: this feature is behind the --harmony runtime flag.
IteratorResult object instead of throwingChrome Full support 49Edge Full support 13Firefox Full support 29IE No support NoOpera Full support 36Safari Full support 10WebView Android Full support 49Chrome Android Full support 49Firefox Android Full support 29Opera Android Full support 36Safari iOS Full support 10Samsung Internet Android Full support 5.0nodejs Full support 6.0.0
Not constructable with new (ES2016)Chrome Full support 50Edge Full support 13Firefox Full support 43IE No support NoOpera Full support 37Safari Full support 10WebView Android Full support 50Chrome Android Full support 50Firefox Android Full support 43Opera Android Full support 37Safari iOS Full support 10Samsung Internet Android Full support 5.0nodejs Full support 6.0.0
Trailing comma in parametersChrome Full support 58Edge Full support 14Firefox Full support 52IE No support NoOpera Full support 45Safari Full support 10WebView Android Full support 58Chrome Android Full support 58Firefox Android Full support 52Opera Android Full support 43Safari iOS Full support 10Samsung Internet Android Full support 7.0nodejs Full support 8.0.0

Legend

Full support
Full support
No support
No support
User must explicitly enable this feature.
User must explicitly enable this feature.

See also