Javascript Iterators and Iterables

“Colorful orange, green, and red Cheerios in a bowl of milk” by David Streit on Unsplash

Iteration is one of those concepts we internalize pretty early in our developer careers. Iterations are building blocks of common algorithms, and most (or every?) programming language has some form of for loop.

However, it took me a while to have a deeper understanding of what iterators and iterables means in Javascript. I only took the time to study them when I faced gotchas on iterating different objects. Here are the things I learned:

Definition

Instinctively, you may think of an iterable as ‘something you can loop through using a forEach’. The trick is to forget that for a moment and think of iterators and iterables simply as objects that follow a very specific interface. From the documentation:

Source: https://www.ecma-international.org/ecma-262/8.0/index.html#sec-iterable-interface. © 2017 Ecma International

Hum, ok. But what is an Iterator object? Hope it is not defined in terms of an Iterable!

Source: https://www.ecma-international.org/ecma-262/8.0/index.html#sec-iterator-interface. © 2017 Ecma International

That is a relief! But what the hell is an IteratorResult?

Source: https://www.ecma-international.org/ecma-262/8.0/index.html#sec-iteratorresult-interface © 2017 Ecma International

Don’t be intimidated by the @@ syntax. This is not even a valid Javascript syntax, it is just a notation used in the specification to refer to ‘well known Symbols’, which are ES6+ built-in symbols that represent internal language behaviour (by the way, many metaprogramming features make use of them). You can access @@iterator through Symbol.iterator.

Iterator and iterables are then quite simple:

  • Iterable: an object that has a @@iterator property, which is a function that return an object following the Iterator Interface.
  • Iterator: an object that has a next property, which is a function that returns an object following the IteratorResult interface.
Figure 1: Relationship between Iterables, Iterators, and IteratorResult.

V8 implementation

So far I knew that an iterable is any object that has a ‘@@iterator’ property, which is a function that returns an iterator. And I also knew that Arrays are iterables, so, I got curious to know if I could see its iterator function.

Hum… ok, I kind of felt stupid trying to console.log source code that is written in C/C++ and compiled LOL. So I went further and looked at the V8 implementation. If you are also curious, please check this file https://github.com/v8/v8/blob/master/src/builtins/builtins-array-gen.cc.

Noniterables objects

Consider an object with three properties. You can loop through all enumerable properties of this object applying a for..in loop. This object is an iterable then, right? Hum, not really. Let’s see if it has a @@iterator.

A common misconception is that all Javascript are iterables, which is not true. That is the reason why you cannot use for…of loops to iterate over objects such as myObj. for…of can only be used to iterate over iterable objects Instead, you should use for…in, which loops over enumerable property names of an object.

Custom iterators and iterables

Most of the time you just need to know if certain data structure follows the iterator/iterable interface or not, so you know which kind of operation you can safely apply on them. But if you need custom behaviour, you can create your own iterators using Generators.

TLDR

Although instinctively you may know what iterables and iterators are, the lack of a deeper understanding can trip you up when trying to iterate a Javascript object. ECMAScript specification provides a straightforward definition for their interfaces. Use them to guide you when you are not sure if a certain method can be applied to a data structure, as well as when you need to implement your own iterables and iterators.