Thank u, [Symbol.iterator].next

Thank u, [Symbol.iterator].next

I’m so f****in’ grateful for this spec

Symbol.iterator

Symbol.iterator is the protocol that makes native objects like Array , Set , and Map iterable by providing a hook into language features like for…of loops and the spread operator.

The most obvious use case is in creating new, iterable data structures that are not provided by the language, like a Linked List. However, Symbol.iterator also lets developers redefine navigation patterns without cloning the object or modifying its order in-place.

These patterns can then be written once in a function, class, or module and used anywhere. That means you can loop through an Array forwards, backwards, randomly, or infinitely in a modular fashion.

The actual Symbol.iterator protocol is very simple. It includes:

Iterable : an object with a function whose key is Symbol.iterator

: an object with a function whose key is Iterator: the above function, used to obtain the values to be iterated

In terms of code:

This tells the Javascript runtime that an Object is iterable. It provides a way to get the next value and check if iteration is done.

If you want more details, there is a great guide on Demystifying ES6 Iterables & Iterators. Otherwise, let’s look at how to use this in practice.

Going Backwards

The two most common ways to iterate an array in reverse are using indices (from array.length — 1 to 0 ), or with Array.reverse :

But both approaches raise concerns. With indices, it can be easy to forget the -1 , leading to the infamous off-by-one error. Using Array.reverse modifies the array in place, which may not always be the intention.

There are entire articles dedicated to this topic, but since we are talking about Symbol.iterator , let me suggest one more way:

Rather than iterating backwards on a given array, we have defined the “going backwards” iteration behavior for any array, all without modifying the order or creating a clone of the original array.

Here is how reverse would work in practice:

Another important aspect of Symbol.iterator is that we do not need an Array-like object to iterate. We can write a function like Python’s range and use it to iterate elegantly over a sequence of numbers.

Note: this implementation of range is very simple. It has not been tested and has clear issues with infinite ranges and negative steps.

We can use range the same way we did reverse :

We can even copy Scala’s Int#to syntax, though you should be cautious when extending a native object’s prototype.

Note: I wrapped the number literal in parentheses to avoid a SyntaxError, but there are other options.