JS: Generator Function

By Xah Lee. Date: . Last updated: .

New in ES2015.

A generator function is a function that returns a generator object.

[see JS: Generator]

Generator function has the following syntax:

generator function declarationfunction * name (…) {…}

generator function expressionfunction * (…) {…}

Generator Method → defined inside object literal expression. {…, * name (…) {…}, …}

[see JS: Object Literal Expression]

The space before or after the asterisk * can be omitted.

Example:

// define a generator function
function * gf () {
    yield 3;
    yield 4;
    yield 5;
}

In the generator function body, you use yield instead of return. Each yield is a stopping point. (explained below.)

Here's a full example showing how it is used.

// example of using generator as iterable

// define a generator function
function * ff () {
    yield 3;
    yield 4;
    yield 5;
}

// generator function returns a generator object
const gg = ff();
// now gg is a generator

// because generator is also a iterable object
// we can use for-of loop on iterable object
for (let p of gg) {
    console.log ( p );
}
// prints
// 3
// 4
// 5

Purpose of Generator Function

Basically the only purpose of generator function is to create generator object.

In the body of generator function, you use yield instead of return. Each yield is a stopping point.

When generator function is called, it returns a generator object.

A generator object is both a Iterable and Iterator.

[see JS: Interface]

So, as a iterable, it can be used in for-of Loop.

Each time a generator is used as iterable (such as in for-of loop), it returns a value at the yield point, and when called again, it resumes computation at that yield point and return the next yield point's value. (this process can be infinite, such as when you have a yield in a infinite loop in the Generator Function body.)

[see JS: for-of Loop]

Most of the time, generator is used as a iterable or iterator.

Generator function provides a easy way to create iterable and iterator.

[see JS: Generator]

Type of Generator Function is Function

Type of Generator Function is a Generator Function object, and typeof operator returns "function".

Type of Generator is Generator object (and not a function object), and typeof operator returns "object".

// define a generator function
function * ff () {
    yield 3;
    yield 4;
    yield 5;
}

// type of Generator Function is function
console.log ( typeof ff === "function" ); // true
console.log ( Object.prototype.toString.call ( ff ) === "[object GeneratorFunction]" ); // true

const gg = ff();

// typo of Generator is object
console.log ( typeof gg === "object" ); // true

console.log ( Object.prototype.toString.call ( gg ) === "[object Generator]" ); // true

[see JS: Determine Type of Object]

Generator Function Constructor

Another way to create generator function is by calling the generator function constructor.

In JavaScript spec, generator function constructor is written as “GeneratorFunction”. But it is not a keyword you can use.

There's no syntax that represents generator function constructor “GeneratorFunction” , but you can get it by:

const GeneratorFunction = Object.getPrototypeOf ( function *(){} ).constructor ;

Once you have the constructor GeneratorFunction, you can create new generator function by the syntax:

GeneratorFunction (p1, p2, … , pn, body)

where all arguments are strings.

It works similarly to Function Constructor.

[see JS: Function Constructor]

For example,

const gf = Object.getPrototypeOf ( function *(){} ).constructor ; const ff = gf ( " yield 3; yield 4; yield 5;" );

is roughly equivalent to:

function * ff () { yield 3; yield 4; yield 5; }

Here's a full example.

const gf = Object.getPrototypeOf ( function *(){} ).constructor ;

// define a generator function
const ff = gf ( " yield 3; yield 4; yield 5;" )

// this is basically equivalent to
// function * ff () { yield 3; yield 4; yield 5; }

// generator function returns a generator object
const gg = ff();
// now gg is a generator object

// because generator is also a iterable object

// we can use for-of loop on iterable object
for (let p of gg) {
    console.log ( p );
}
// prints
// 3
// 4
// 5

In general, there's no practical use of Generator Function constructor. Use the syntax function * name () {…} instead.

The reason the generator function constructor object exist is so that JavaScript can maintain some language structure consistency. That is, each object X has a constructor object C that creates instances of X, and the constructor object C has property "prototype" that is the parent object of instances of X, etc.

Reference

ECMAScript 2015 §Control Abstraction Objects#sec-generatorfunction-objects

Iterable / Iterator / Generator Topic

  1. JS: Interface
  2. JS: Iterable
  3. JS: Iterator
  4. JS: for-of Loop
  5. JS: Generator Function
  6. JS: Generator
Liket it? Put $5 at patreon.

Or, Buy JavaScript in Depth

Ask me question on patreon