ES6 – Generators

Hi, in this post we are going to learn about generators of ES6.

A generator function is similar to a normal function, the difference is that instead of return a single value, it will return multiple values one by one.

The generator functions are functions that we can pause or stop them and then latter we can access to the function and this function will keep the same context

If we call the generator function this doesn’t execute its body immediately, but rather will return a new instance of the generator object.

Every generator object (generator object implement iterable and iterator protocol) hold a new execution context of the generator function.

When the next() method is executed this executes the generator function’s body until yield keyword is encountered.

It returns the yield value, and pauses the function, then when the next() method is called again, it resumes the execution, and then returns the next yielded value and the done property will be true when the generator function doesn’t yield any more.

We write a generator function like this:

 function* name_of_my_generator_function() { }

Take a look of my my_generator_function in this code:

function* my_generator_function() {
  yield 100;
}

let generator = my_generator_function();

console.log("generator object --->", generator.next()); // { value: 100, done: false }
console.log("generator object --->", generator.next()); // { value: 100, done: true }

If you see I’m consoling the generator.next() and this will return us an object (generator object) with 2 properties value and done.

value property: have each value of the generator function.

done property: if the generator function have more values then done will be false, until the generator function doesn’t have more values to show (true).

So the basic concepts for generators functions are:

  • A generator function need the yield keyword to return its values partially
  • A generator function keep its context all the time
  • The generator object implement iterable and iterator protocol so in that way we used the next() method
  • A generator function will return a new instance of the generator object and this generator object have value and done properties.

Here entire example:

function* my_generator_function() {
  yield 100;
  yield 200;
  yield 300;
  yield 400;
  yield 500;
}

let generator = my_generator_function();

console.log("value --->", generator.next().value); // 100
console.log("value --->", generator.next().value); // 200
console.log("value --->", generator.next().value); // 300
console.log("value --->", generator.next().value); // 400
console.log("value --->", generator.next().value); // 500
console.log("value --->", generator.next().done); // true

Note: yes, the generator functions can have parameters.

Result:

Iterable protocol

function* my_generator_function() {
  yield 100;
  yield 200;
  yield 300;
  yield 400;
  yield 500;
}

let generator = my_generator_function();

let iterable = generator[Symbol.iterator]();

console.log("value --->", iterable.next().value); // 100
console.log("value --->", iterable.next().value); // 200
console.log("value --->", iterable.next().value); // 300
console.log("value --->", iterable.next().value); // 400
console.log("value --->", iterable.next().value); // 500
console.log("value --->", iterable.next().done); // true

Result:

Optional argument in next() method

We can pass and optional argument in next() method, the argument becomes the value returned by the yield keyword.

function* my_generator_function() {
  var a = yield 100;
  var b = yield a + 200;
  var c = yield b + 300;

  yield c + 300;
}

let generator = my_generator_function();

console.log("value --->", generator.next().value);
console.log("value --->", generator.next(500).value);
console.log("value --->", generator.next(1000).value);
console.log("value --->", generator.next(6000).value);
console.log("value --->", generator.next().done);

Result:

By Cristina Rojas