Show Buttons
Share On Facebook
Share On Twitter
Share On Google Plus
Share On Linkdin
Share On Reddit
Share On Stumbleupon
Contact us
Hide Buttons

Getting started with es6 iterators and iterables

ES6 iter­a­tors pro­vide a very sim­ple way to iter­ate on objects, quite sim­i­lar to the way iter­a­tors work in Java. In this post, I will briefly dis­cuss the main con­cepts behind ES6 iter­a­tors and then dive into some exam­ples using arrays. Future posts will dis­cuss using ES6 iter­a­tors with other kinds of objects. This arti­cle is the sec­ond install­ment of our Learn­ing ES6 series.


A brief introduction

There are a few things you ought to know before we jump in and see some examples.

  • There are two main types of enti­ties to be aware of: iterables and iterators.
  • Iter­ables are things that can be iter­ated upon, like arrays, Maps, Sets.
  • Prim­i­tive javascript objects are not iterable.
  • Any­thing that imple­ments the next() func­tion can be con­sid­ered to be an iterator.
  • The result of invok­ing next() is (almost) always object of the form {value: some_value, done: true|false }.
  • Any object/function can be turned into an iter­able if it has a key called Symbol.iterator which refers to a func­tion that returns an object with the next() function.

If you didnt get all of it right away, dont worry, I didnt either. Lets bite off this cake piece by piece.

NOTE: If your browser does not sup­port run­ning all the foll­wing exam­ples, you can try them out at es6fiddle.net.


Basic iter­a­tion

Arrays are the sim­plest and the most com­mon iter­ables. Tra­di­tion­ally, you could iter­ate on arrays as follows

var numbers = ['a', 'b'];
for (var num in numbers) {
  console.log(num);
}

Using the new ES6 iter­a­tors you can iter­ate on an array as follows:

var numbers = ['a', 'b'];
var iter = numbers[Symbol.iterator]();
console.log(iter.next()); // Prints {value: "a", done: false}
console.log(iter.next()); // Prints {value: "b", done: false}
console.log(iter.next()); // Prints {value: undefined, done: true}

In ES6 Symbol.iterator is a non-string key for iter­ables that is invoked to cre­ate an instance of an iter­a­tor. In fact, Symbol is a com­pletely new prim­i­tive type in ES6. As you can tell in the above code, the key is already avail­able on the Array prim­i­tive type. All we did was invoke it to cre­ate a new iterator.

Also, in the above code, notice how the last value of iter.next() returns the done as true. This can be used in your pro­gram to deter­mine if there are more items to iter­ate on.

Hav­ing to invoke Symbol.iterator on a prim­i­tive like arrays seems like a bit of an over­head. Thats not to worry because you can also use Array.prototype.entries() to cre­ate the exact same iter­a­tor, albeit in a much more con­ve­nient syntax.

var numbers = ['a', 'b'];
var iter1 = numbers.entries();
// is equivalent to
var iter2 = numbers[Symbol.iterator]();

The entries() func­tion is avail­able on ES6 prim­i­tives like arrays, typed arrays, maps and sets. In fact, they also have two more use­ful func­tions — keys() and val­ues() which do pretty much what you think they do.


Dif­fer­ent ways to iterate

Another point to note is that depend­ing on the way you iter­ate, you can expect a dif­fer­ent kind of out­put. For example.

var numbers = ['a', 'b'];
var iter1 = numbers.entries();

console.log(iter1.next()); // Prints {value: "a", done: false}
console.log(iter1.next()); // Prints {value: "b", done: false}
console.log(iter1.next()); // Prints {value: undefined, done: true}

// Compare the above output to the following
for (var item of numbers.entries()) {
    console.log(item);
}
// Output
// [0, "a"]
// [1, "b"]

Notice in the above code, we had to use the for..of loop for this to work instead of the for..in loop. As far as the out­put is con­cerned, the first item of the out­put array rep­re­sents the key in the entry, which in our case is the index, and the sec­ond item in the out­put array is the actual value of the num­bers array.

The return value of the entries() func­tion makes it suit­able can­di­date for being used along with the spread oper­a­tor.

for (var [index, item] of numbers.entries()) {
    console.log(index, item);
}
// Output
// [0, "a"]
// [1, "b"]

If you wish to, you can also iter­ate on the keys itself. This isin’t as use­ful in the case of arrays but comes in really handy when you are using Maps.

var coordinates = new Map();
coordinates.set('x', 10);
coordinates.set('y', 20);

for (var item of coordinates.keys()) {
    console.log(item);
}
// Output
// x
// y

NOTE: ES6 Maps, unlike reg­u­lar javascript objects, return val­ues based on inser­tion order when iter­ated on.

The next and final util­ity func­tion on prim­i­tives is the value() func­tion. And as you would expect, it lets you iter­ate on the values.

var coordinates = new Map();
coordinates.set('x', 10);
coordinates.set('y', 20);

for (var item of coordinates.values()) {
    console.log(item);
}
// Output
// 10
// 20

That cov­ers all the ways in which you can use the new ES6 iter­a­tors. In the next arti­cle, we will see more exam­ples of cre­at­ing and using your own iter­a­tors and also dis­cuss some of the optional but often times nec­es­sary func­tions like return().


You may also like...