JavaScript Generators


Generators are a special kind of function in JavaScript that can be paused and resumed, allowing you to produce a sequence of values over time without creating an array to store them all at once. This makes them memory efficient for working with large datasets or infinite sequences.

Defining a Generator:

Generators are defined using an asterisk (*) after the function keyword or before the function name in arrow functions. They use the yield keyword to return a value and pause execution.

function* myGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const anotherGenerator = function* () {
  yield 'a';
  yield 'b';
  yield 'c';
};

const arrowGenerator = *() => {
  yield true;
  yield false;
};

Using a Generator:

You interact with a generator through its iterator. Calling the generator function doesn’t execute its body. Instead, it returns an iterator object.

const gen = myGenerator();

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 }

Each call to next() on the iterator resumes the generator, executes until the next yield, and returns an object with the yielded value and a done flag indicating whether the generator has finished.

Iterating over a Generator:

You can easily iterate over a generator using a for...of loop:

for (const value of myGenerator()) {
  console.log(value); // 1, 2, 3
}

Example: Generating an Infinite Sequence:

Generators are excellent for representing infinite sequences because they generate values on demand.

function* infiniteCounter() {
  let i = 0;
  while (true) {
    yield i++;
  }
}

const counter = infiniteCounter();

console.log(counter.next().value); // 0
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
// ... and so on

Example: Generating Fibonacci Numbers:

function* fibonacci() {
  let a = 0;
  let b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = fibonacci();

for (let i = 0; i < 10; i++) {
  console.log(fib.next().value); // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
}

Generators provide a powerful and efficient way to work with sequences of data in JavaScript, especially when dealing with large datasets or infinite sequences. They are a valuable tool for any JavaScript developer to understand.