ES6 Iteration Protocol

This is the part of a series of blogs on the new features on the upcoming ECMAScript 6 (ES6) specification which JavaScript implements.

In this blog we focus on the iteration protocol introduced in ES6.

Iteration #

Lets take a quick programming 101 background. An iterator is basically a sequence generator. A sequence is an ordered list of values whose order and uniqueness does not matter. A trivial example of a sequence is the Array.

So an iterator is just an abstraction of, for example, a for loop. It has certain functions such as prev, next, valid, key, and value to go through the sequence, iterating through the elements.

We do the iteration to save memory by only generating values that are needed when they are needed. This is done by dynamically performing instructions based on the iteration.

Think about a for loop that ends when i > 5 and breaks; rather than going through the entire array checking if the validity statement (that i > 5) still holds.

Iterable Protocol #

The Iterable Protocol allows us to define or customize the object’s iteration behavior such as when it is looped over in a for .. of construct.

For an object to be iterable, it must implement the @@iterator method by defining a property with a Symbol.iterator key.

Some native objects are inherently iterable because of their prototype inheritance such as String, Array, TypedArray, Map, and Set.

Example of a defined iterable:

var hermioneGranger = {};
hermioneGranger[Symbol.iterator] = function* () {
    yield 'Hermione';
    yield 'Jean';
    yield 'Granger';
};
for (let name of hermioneGranger) {
    console.log(name);
}
// "Hermione"
// "Jean"
// "Granger"

There are also builtin APIs that take on iterable objects such as Map, WeakMap, Set, and WeakSet. Learn more about them at my previous blog.

To use iterable objects however you can use the natively exposed methods of iterating through the iterable objects such as for-of loops (as seen above), spread operator, yield*, and destructuring assignment.

Example:

/* For Of Loop */
for (let name of hermioneGranger) {
    console.log(name);
}
// "Hermione"
// "Jean"
// "Granger"

/* Spread Operator */
[...hermioneGranger] // ["Hermione", "Jean", "Granger"]

/* Yield */
// From the yield function above
hermioneGranger().next(); // { value: "Hermione", done: false }
hermioneGranger().next(); // { value: "Jean", done: false }
hermioneGranger().next(); // { value: "Granger", done: false }
hermioneGranger().next(); // { done: true }

/* Destructuring Assignment */
[a, b, c] = new Set(hermioneGranger);
a; // "Hermione"

Iterator Protocol #

The Iterator Protocol defines a standard way to produce a sequence of values.

For an object to be an iterator it must implement the next() method with the following constraints:

next()

Example:

function idMaker(){
    var id = 0;

    return {
       next: function(){
           return {value: id++, done: false};
       }
    };
}

var it = idMaker();
console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.next().value); // 2
console.log(it.next().done); // false
console.log(it.next().value); // 4

Differences #

Inherently iterators and iterables are two different things. However an object could be both an iterator and an iterable at the same time

Example:

var name = ['harry', 'james', 'potter'];
var nameEntries = name.entries();

nameEntries.toString(); // "[object Array Iterator]"
nameEntries === nameEntries[Symbol.iterator](); // true

A perfect example of this is a generator object which is both an iterator and is iterable.

 
7
Kudos
 
7
Kudos

Now read this

Enhancing JavaScript Arrays: Good or Bad?

This is a way to give JavaScript Arrays some extra functionality to make life easier for development and in turn lead to clear and concise code. I’ve mentioned some ways to give backwards compatibility functionality (otherwise known as... Continue →