Iterators in Javascript

Raymond Chow
3 min readOct 5, 2019

--

If you have ever programmed in Javascript before, you probably have used the for…of syntax to iterate over an array. For example,

const arr = [1,2,3];for( let i of arr ) {
console.log(i);
}
// 1
// 2
// 3

Under the hood, the for…of is actually using an iterator to iterate over the array! Furthermore, the for…of can be used to to iterate over anything as long as that thing provides an iterator. For example, you can iterate over a Set,

const set = new Set([1,2,3])

for(let i of set) {
console.log(i)
}
// 1
// 2
// 3

So what is actually happening under the hood in the code below?

const arr = [1,2,3];for( let i of arr ) {
console.log(i);
}
// 1
// 2
// 3

Arrays in Javascript have an iterator property that is hidden. This iterator tells the for..of loop how to iterate it. To access the iterator of arr in the code above, you can write this line of code:

const iterator = arr[Symbol.iterator](); //Array Iterator {}

So what is this line of code doing exactly? We are first accessing the Array iterator by grabbing the value of arr[Symbol.iterator]. What is this Symbol thing? Symbols in JavaScript are a primitive data type. They are anonymous, unique values that may be used as an object property. The purpose of Symbols is to avoid name clashes between properties. The value of arr[Symbol.iterator] is a function that when executed, returns an Iterator object. This Iterator object has a next() function inside. What happens when you invoke the next() function?

iterator.next(); // {value: 1, done: false}

It gives you an object with two properties: value and done. If you call next() a few more times, you will get:

iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: false}
iterator.next() // {value: undefined, done: true}

So everytime you call next(), you get the next item in the array until you reach the end. At the end, the value of done property becomes true.

With Iterators, you can create your own custom Iterables! For example:

class Range {
constructor(start, end) {
this.start = start
this.end = end;
}
[Symbol.iterator]() {
let [current, end] = [this.start, this.end];
return { //returns the iterator object
next() { //implementing next() method
if (current >= end) {
return { done: true }
} else {
return { value: current++, done: false }
}
}
}
}
}

The code above defines a custom Iterable called Range. It’s elements are all the numbers between the start and end provided. It makes sure to define a function [Symbol.iterator]() that returns an object with a next() function. The next() function returns an object with two properties value and done.

Here is how you would use Range:

let range = new Range(5, 11);

for (let n of range) {
console.log(n);
}
// 5
// 6
// 7
// 8
// 9
// 10

Iterators are a powerful tool in Javascript that allows you to build custom collections of data (Iterables). I hope this blog helped shed some light on how the for…of loop works behind the scenes, and how to build your own custom Iterable.

--

--