Be the first user to complete this post

  • 0
Add to List

Getting started with es6 iterators and iterables

ES6 iterators provide a very simple way to iterate on objects, quite similar to the way iterators work in Java. In this post, I will briefly discuss the main concepts behind ES6 iterators and then dive into some examples using arrays. Future posts will discuss using ES6 iterators with other kinds of objects. This article is the second installment of our Learning 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 entities to be aware of: iterables and iterators.
  • Iterables are things that can be iterated upon, like arrays, Maps, Sets.
  • Primitive javascript objects are not iterable.
  • Anything that implements the next() function can be considered to be an iterator.
  • The result of invoking next() is (almost) always object of the form {value: some_value, done: true|false }.
  • Any object/function can be turned into an iterable if it has a key called Symbol.iterator which refers to a function 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 support running all the follwing examples, you can try them out at es6fiddle.net.

Basic iteration

Arrays are the simplest and the most common iterables. Traditionally, you could iterate on arrays as follows
var numbers = ['a', 'b'];
for (var num in numbers) {
  console.log(num);
}
Using the new ES6 iterators you can iterate 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 iterables that is invoked to create an instance of an iterator. In fact, Symbol is a completely new primitive type in ES6. As you can tell in the above code, the key is already available on the Array primitive type. All we did was invoke it to create 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 program to determine if there are more items to iterate on. Having to invoke Symbol.iterator on a primitive like arrays seems like a bit of an overhead. Thats not to worry because you can also use Array.prototype.entries() to create the exact same iterator, albeit in a much more convenient syntax.
var numbers = ['a', 'b'];
var iter1 = numbers.entries();
// is equivalent to
var iter2 = numbers[Symbol.iterator]();
The entries() function is available on ES6 primitives like arrays, typed arrays, maps and sets. In fact, they also have two more useful functions - keys() and values() which do pretty much what you think they do.

Different ways to iterate

Another point to note is that depending on the way you iterate, you can expect a different kind of output. 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 output is concerned, the first item of the output array represents the key in the entry, which in our case is the index, and the second item in the output array is the actual value of the numbers array. The return value of the entries() function makes it suitable candidate for being used along with the spread operator.
for (var [index, item] of numbers.entries()) {
    console.log(index, item);
}
// Output
// [0, "a"]
// [1, "b"]
If you wish to, you can also iterate on the keys itself. This isin't as useful 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 regular javascript objects, return values based on insertion order when iterated on.
The next and final utility function on primitives is the value() function. And as you would expect, it lets you iterate 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 covers all the ways in which you can use the new ES6 iterators. In the next article, we will see more examples of creating and using your own iterators and also discuss some of the optional but often times necessary functions like return().



Also Read:

  1. Using es6 modules with simple examples
  2. css: margin does not work
  3. Progressive enhancement vs Graceful degradation
  4. The JavaScript Prototype Property - Visualized
  5. Split a string in javascript when both comma and spaces are present