Generators in ES6

ECMAScript 6, otherwise known as ES6 or ES2015, adds many features of a modern language to the oft lampooned JavaScript. The addition of the generator adds some functional programming capabilities in the same vein as the generator found in Python. Essentially, the generator allows for lazy evaluation.

Note: ES6 isn’t supported universally, so for now we use a transpiler like Babel to convert to ES5.

Why is lazy evaluation a good thing? The run-time will only evaluate what it needs, saving potential memory and computation.

Here we have a generator function definition denoted by the asterisk (*).

When called, it returns an iterable generator object. The code within the generator isn’t evaluated until the method “next” is called.
Each call to “next” executes the code until the next “yield” statement, which returns an object with its current value and status.

const gen = simple();; // { value: 1, done: false }; // { value: 2, done: false }; // { value: 3, done: false }

If there are no more executable “yield” statements, “next” will return:; // { value: undefined, done: true }

Now let’s try using this lazy evaluation to describe a function by what it is, rather than what it does.

This generator function describes the Fibonacci sequence by simply stating its properties: each consecutive value is the sum of the two previous values.
This allows you to take from it what you need, rather than transforming its meaning to a specific use imperatively.

While ES6 is making great strides, I still missed some built-in generator methods, so I tried my hand at adding some helper methods like Haskell’s take function.

I added the method to both the Generator and the GeneratorFunction for convenience, so I can do things like this:

[...fibonacci.take(10)]; // [ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
const f = fibonacci();
f.take(10); // [ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
f.take(7); // [ 89, 144, 233, 377, 610, 987, 1597 ]

Let’s try a more practical use. ES6 added the new primitive type Symbol. You can customize the iteration of an instance object with a generator function Symbol.iterator defined in its prototype. Here’s a simple linked list with some stack operations to demonstrate:

This iterator allows you to use the spread operator (…) as well as the for..of loop.

const stack = new LinkedListStack();
console.log(...stack); // Prints: 'hello world!'
for (const v of stack) {
console.log(v); // Prints: 'hello\nworld!'

Thanks for the read! Let me know what you think in the comments below.