We've seen the implementation of Array Comprehensions introduced in earlier versions of ECMAScript 6 where we can easily construct a new array based on the contents of another using a "comprehension." Comprehensions are great for small arrays without a heavy memory footprint but the reality is that they can be expensive when applied to larger arrays. The main reason for the degradation of performance is attributed to the additional overhead created when computing the result of the comprehension during runtime.
Below is an example of an array comprehension that takes the original array of numbers and generates a second result set with each number added to a value of 4.
To address this problem, the generator expression was introduced. Generators enable us to iterate through an object using lazy computations that generate values in the sequence based on the generator logic. The idea of generators has been borrowed from python (see http://wiki.python.org/moin/Generators). Array comprehensions compile the entire resultant set when evaluated whereas a generator allows us to iterate through a set on an as-needed basis, only computing values when requested.
Generators are a unique kind of function that can be suspended and resumed. They have a
yield operator that acts as a return and pauses the iterator but the key here is that when the generator is resumed, it continues at the previous
yield instead of being freshly evaluated.
The code above is an example of how we can declare a new generator. Note the
*(asterisk) after the
function operator; this denotes we are declaring a generator vs a normal function.
When a generator function is called, a generator object is returned. At the time of writing this article, we have access to a few methods available on the generator prototype:
next() can take a value that will advance the iterator to that position (or reset it depending on the position of that value).
In the code above, you can see an example of a generator that demonstrates iteration through the fibonacci sequence.
Recursion in generators is a little different than what you're probably accustomed to. In any normal scenario, you might implement recursion something like this:
If we were to implement this same type of recursion for a generator by calling itself through
recursivelyIterateThrough() it wouldn't actually work because if you remember from earlier, calling a generator function returns a new generator object. So if we don't have access to the parent scope, how do we perform recursion then? ECMAScript 6 provides a
yield* operator specifically for this case.
yield* returns everything that was yielded by the iterable that is its operand.
A slightly tweaked version of the
recursivelyIterateThrough() function above, compliant with generator specifications, would look something like this:
If you want to give generators a try, check them out in a recent version of Firefox but be sure to keep in mind, they work slightly different than the ECMAScript 6 standards. You can review the cross-browser compatibility of generators at any time by checking out the [ECMAScript 6 compatibility table](http://kangax.github.io/es5-compat-table/es6/#Generator expressions). For additional information on the ECMAScript 6 generator standards refer to http://wiki.ecmascript.org/doku.php?id=harmony:generators.