JavaScript
Article
By Byron Houwens

ECMAScript 2015: Generators and Iterators

By Byron Houwens

A few days ago ECMAScript 2015, also known as ECMAScript 6 or ES6, was accepted as an official standard. Even though this event happened very recently, there are already a number of features supported in the latest versions of Chrome, Firefox, Safari, and Opera. If you’re really itching for the ES6 goodness, you can even use a number of well-supported transpilers right now.

Two of the new features, generators and iterators, are set to change some of the ways we write specific functions when it comes to some more complex front-end code. While they do play nicely with one another, what they actually do can be a little confusing to some, so let’s check them out.

Iterators

Iteration is a common practice in programming and is usually used to loop over a set of values, either transforming each value, or using or saving it in some way for later.

In JavaScript we’ve always had for loops that look like this:

for (var i = 0; i < foo.length; i++){
   // do something with i
}

But ES6 gives us an alternative:

for (var i of foo) {
   // do something with i
}

This is arguably way cleaner and easier to work with, and reminds me languages like Python and Ruby. But there’s something else that’s pretty important to note about this new kind of iteration: it allows you to interact with elements of a data set directly.

Imagine that we want to find out if each number in an array is prime or not. We could do this by coming up with a function that does exactly that. It might look like this:

function isPrime(number) {
   if (number < 2) {
      return false;
   } else if (number === 2) {
      return true;
   }

   for (var i = 2; i < number; i++) {
      if (number % i === 0) {
         return false;
         break;
      }
   }

   return true;
}

Not the best in the world, but it works. The next step would be to loop over our list of numbers and check whether each one is prime with our shiny new function. It’s pretty straightforward:

var possiblePrimes = [73, 6, 90, 19, 15];
var confirmedPrimes = [];

for (var i = 0; i < possiblePrimes.length; i++) {
   if (isPrime(possiblePrimes[i])) {
      confirmedPrimes.push(possiblePrimes[i]);
   }
}

// confirmedPrimes is now [73, 19]

Again, it works, but it’s clunky and that clunkiness is largely down to the way JavaScript handles for loops. With ES6, though, we’re given an almost Pythonic option in the new iterator. So the previous for loop could be written like this:

let possiblePrimes = [73, 6, 90, 19, 15];
let confirmedPrimes = [];

for (let i of possiblePrimes){
    if ( isPrime(i) ){
        confirmedPrimes.push(i);
    }
}
	 
// confirmedPrimes is now [73, 19]

This is far cleaner, but the most striking bit of this is that for loop. The variable i now represents the actual item in the array called possiblePrimes. So, we don’t have to call it by index anymore. This means that instead of calling possiblePrimes[i] in the loop, we can just call i.

Behind the scenes, this kind of iteration is making use of ES6’s bright and shiny Symbol.iterator() method. This bad boy is in charge of describing the iteration and, when called, returns a JavaScript object containing the next value in the loop and a done key that is either true or false depending on whether or not the loop is finished.

In case you’re interested in these sort of details, you can read more about it on this fantastic blog post titled Iterators gonna iterate by Jake Archibald. It’ll also give you a good idea of what’s going on under the hood when we dive into the other side of this article: generators.

Generators

Generators, also called “iterator factories”, are a new type of JavaScript function that creates specific iterations. They give you special, self-defined ways to loop over stuff.

Okay, so what does all that mean? Let’s look at an example. Let’s say that we want a function that will give us the next prime number every time we call it. Again, we’ll use our isPrime function from before to check if a number is prime:

function* getNextPrime() {
   let nextNumber = 2;

   while (true) {
      if (isPrime(nextNumber)) {
         yield nextNumber;
      }
      nextNumber++;
   }
}

If you’re used to JavaScript, some of this stuff will look a bit like voodoo, but it’s actually not too bad. We have that strange asterisk after the keyword function, but all this does is to tell JavaScript that we’re defining a generator.

The other funky bit would be the yield keyword. This is actually what a generator spits out when you call it. It’s roughly equivalent to return but it keeps the state of the function instead of rerunning everything whenever you call it. It “remembers” its place while running so the next time you call it, it carries on where it left off.

This means that we can do this:

var nextPrime = getNextPrime();

And then call nextPrime whenever we want, you guessed it, the next prime:

console.log(nextPrime.next().value); // 2
console.log(nextPrime.next().value); // 3
console.log(nextPrime.next().value); // 5
console.log(nextPrime.next().value); // 7

You get the picture. You can also just call nextPrime.next(), which is useful in situations where your generator isn’t infinite, because it returns an object like this:

console.log(nextPrime.next());
// {value: 2, done: false}

Where that done key tells you whether the function has completed its task. In our case our function will never finish, and could theoretically give us all prime numbers up to infinity (if we had that much computer memory, of course).

--ADVERTISEMENT--

Cool, so Can I Use This Now?

Although ECMAScript 2015 has been finalized, browser support for its features, particularly generators, is not excellent. If you really want to use these and other new features, you can check out transpilers like Babel and Traceur, which will convert your ECMAScript 2015 code into its equivalent (where possible) ECMAScript 5 code.

There are also many online editors with support for ECMAScript 2015 or that specifically focus on it, particularly Facebook’s Regenerator and JS Bin. If you’re just looking to play around and get a feel for how JavaScript will be written in the near future, those are worth a look.

Conclusions

Iterator and generators give us quite a lot of new flexibility in our approach to JavaScript problems. Iterators allow us a more Pythonic way of writing for loops, which means our code will look cleaner and be easier to read.

Generator functions give us the ability to write functions that remember where they were when you last saw them, and can pick up where they left off. They can also be infinite in terms of how much they actually remember, which can come in really handy in certain situations.

Although browser support for these features isn’t great yet, there are a number of transpilers and online editors with enough support for you to get your hands dirty if you’re keen. Anyway, I think we, as developers using these new features, will really love what they have to offer.

Recommended
Sponsors
The most important and interesting stories in tech. Straight to your inbox, daily. Get Versioning.
Login or Create Account to Comment
Login Create Account