JavaScript Iterators and Iterables
Tags: javascript, programming, beginners
Published: 2019-07-17 11:11:21

---
title: JavaScript Iterators and Iterables
layout:
description: In our first in-depth post on JavaScript, we take a look at Iterators and Iterables
tags: javascript, programming, beginners
canonical_url: https://blog.appsignal.com/2019/07/16/javascript-iterators-and-iterables.html
cover_image: https://blog.appsignal.com/images/blog/2019-07/iterators.jpg
published:  true
---

Welcome to our first in-depth post on JavaScript! Here at AppSignal, we're gearing up to launch our all-new front-end monitoring solution, something we're very excited about and hope you will be, too.

Over the last few years, I've watched JavaScript evolve from somewhat of an oddity—an admittedly imperfect, but often misunderstood, scripting language for the browser—to a powerful and expressive language in its own right, deployable in multiple environments, and almost ubiquitous in today's computing landscape.

The aim of this corner of [AppSignal.com](http://appsignal.com) is to explore this language in greater detail and uncover The Good Parts™ that make JavaScript awesome. Much like our sister blogs, [Ruby Magic](https://blog.appsignal.com/category/ruby-magic.html) and [Elixir Alchemy](https://blog.appsignal.com/category/elixir-alchemy.html), we'll deep-dive into language features, patterns and frameworks, and share some other JavaScript insights along the way, too.

Let's get to it! But first, let's talk about Ruby.

## On Linked Lists and Rubyists

In [a previous edition of Ruby Magic](https://blog.appsignal.com/2018/05/29/ruby-magic-enumerable-and-enumerator.html), Jeff explored Ruby's `Enumerator` objects and `Enumerable` module. This is described by Jeff like this:

> Enumeration refers to traversing over objects. In Ruby, we call an object enumerable when it describes a set of items and a method to loop over each of them.

Alright, sounds useful! I can already see plenty of reasons why you'd want this. In the aforementioned post, Jeff uses `Enumerable` to implement a [Linked List](https://en.wikipedia.org/wiki/Linked_list) — a common, almost evergreen data structure type that is a collection of data elements, in which each element points to the next. Each element in the list has two values, named the head and the tail. The head holds the element’s value, and the tail is a link to the rest of the list.

By ensuring that the linked list responds to the `#each` method, and by including the `Enumerable` module, it's possible to implement this data structure in Ruby without writing a whole mess of code. This got me thinking - I wonder if JavaScript can do something like that?

The answer: yes, it can! But, this wouldn't be a JavaScript blog post unless I told you that, of course, things are a little different here. Today, we're going to introduce you to JavaScript's close relative of Ruby's `Enumerable` class, the *[Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)*, and how we can leverage it to write a `LinkedList` class of our own.

Some of you may have never had to have implemented a Linked List before. No doubt, many of you have had to have implemented one as part of a job interview. Perhaps you, [like the React team](https://medium.com/react-in-depth/the-how-and-why-on-reacts-usage-of-linked-list-in-fiber-67f1014d0eb7), are already using them to do non-trivial things in your codebase. The example we'll be implementing today is almost an exact port of Jeff's Ruby `LinkedList` class to JavaScript, which I really like due to the simplicity of the implementation. It is, perhaps, a little easier to grasp what's going on here than it would otherwise be with a "full-fat" implementation.

It doesn't catch all the edge cases, or provide a number of class methods that you might expect, but should help illustrate the idea. Consider yourself warned: you will be sent to programming hell if I catch you using this code in production, and there, no amount of random key combinations will help you exit Vim.

Okay, let's begin.

## So, what's an iterator?

An iterable in JavaScript is an object that defines custom iteration behaviour via a method on itself or any of the objects in its prototype chain. You're probably already quite familiar with some of the built-in JavaScript types that are iterables, chiefly `Array`, `Map`, `Set` and `String`. In common programming parlance, we say that these types can be "looped over"; given a construct like a `for` loop, we can extract each value in order from the iterable and do something with it. 

JavaScript provides the `for...of` loop for iterating over a generic iterable:

```javascript
for (let value of iterable) { 
  console.log(value); 
}
```

You can also *[destructure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)* an iterable to get a subset of its values as named variables. In the following example, `a === 'a'` and `b === 'b'`:

```javascript
const [a, b] = new Set(['a', 'b', 'c']);
```

Iterables can even be spread into an array literal, transforming your iterable into a linear array and allowing you to call array methods like .map() or .filter() on the returned value:

```javascript
[...iterable].map(el => console.log(el));
```

So what makes an object iterable? Here's where things start to get a little more advanced. 

## `@@iterator` - The Invisible Property

In order to become an iterable, a special function must be implemented on the object itself - `@@iterator`. Now, to many of you out there, you would be forgiven to have been blissfully unaware that this property ever existed. It can't be accessed by calling `iterable.@@iterator`. It doesn't show up in a  `for` loop or when calling `Object.keys` on an iterable. Often, `console.log` won't even reveal this property. So, where is it?

Unlike other programming languages, JavaScript doesn't [(yet)](https://github.com/tc39/proposal-private-methods) have the concept of private methods or private fields on an object, but we can make a property of an object "pseudo-private" by referencing it using a special JavaScript type called a [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol). The `@@iterator` property is implemented in this way: the value of the `@@iterator` property can only be referenced using a `Symbol` key that is defined as a constant on the `Symbol` type itself: `Symbol.iterator`. 

Accessing it works like this:

```javascript
class LinkedList {
  // ...
  [Symbol.iterator]() {}
}

// ...or using an object literal
const LinkedList = {};
LinkedList[Symbol.iterator] = function () {};
```

On a given `class` or object, where the key is `Symbol.iterator`, the value must be a function. In a classic, synchronous implementation of an iterator, this function returns an object (called an *iterable*) that implements a function called `next()` as a property. Let's expand a little further on our example to see what this looks like:

```javascript
class LinkedList {
  // ...
  [Symbol.iterator]() {
    return {
      next() {
        return {
          value: "a value",
          done: false
        }
      }
    }
  }
}
```

Holy nested statements! We've managed to erect a small pyramid in our shiny new codebase, but we have successfully implemented an *iterator* that returns an *iterable*. The iterable itself returns an object with two properties: `value` and `done`. Unsurprisingly, `value` is the current value of the iterator, and `done` is a boolean value to communicate to the iterator if the sequence of values has ended. If `done === true`, then the `value` property can be emitted.

Now we know a little more about how iterators and iterables work, let's see how we can apply this knowledge to build a `LinkedList`.

## Building the `LinkedList`

Let's start out by just porting Jeff's Ruby class into JavaScript, sans the `#each` method used to create an `Enumerable`:

```javascript
class LinkedList {
  constructor(head = null, ...rest) {
    this.head = head;
    
    if (rest[0] instanceof LinkedList) {
      this.tail = rest[0];
    }
    // roughly equivalent to `rest.any?` in ruby
    else if (rest.some(el => el)) {
      this.tail = new LinkedList(...rest);
    }
    else {
      this.tail = null;
    }
  }

  add(item) {
    return new LinkedList(item, this);
  }
}
```

So far, so good. Using the above example, we can already create a new `LinkedList`, and add new items to the head of the `LinkedList`, using the *[rest](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) and [spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)* operator (`...`) to create the tail. As the first argument to the constructor, we allow anyone using our `LinkedList` class to pass a `head` as the top of the linked list, and the *rest* operator in the `constructor` is able to convert any remaining arguments that are not `head`, and convert them to an array. The `else if` statement creates a new `LinkedList` from this array, and continues to do so until the last item in `rest` belongs to the `head` of a `LinkedList`.

Now, we'll need to implement the logic to retrieve the items from the `LinkedList`, but I can already see a problem. If we implement an iterator, and the subsequent iterable, using the technique outlined above, then we're already deviating from Jeff's initial design quite considerably. There's a lot more code to write, and we'll need to maintain state somehow, as we need to tell the iterable that our sequence is finished by setting `done` to `true`. It's certainly possible, but I think we can come up with something more elegant.

Enter the Generator function.

## Generator functions

The value we set as `Symbol.iterator` can also be a [generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*), a new type of function that was introduced with ECMAScript 2015. The easiest way to think of a generator function is a function that you can exit and return to at will, optionally returning a value with the `yield` keyword. Using the power of [closures](https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md), we can maintain the state of the function across multiple `yield`s and re-entries. Importantly, generator functions have the same interface as an iterable, meaning values can be retrieved in the same manner as if we had implemented the iterable ourselves.

Let's implement an iterator to get all of the values from our `LinkedList` using a generator function:

```javascript
class LinkedList {
  // ...implementation

  *[Symbol.iterator]() {
    yield this.head;
    let next = this.tail;

    while (next !== null) {
      yield next.head;
      next = next.tail;
    }
  }
}
```

## The Full Implementation

So, when all is said and done, this is what we end up with:

```javascript
class LinkedList {
  constructor(head = null, ...rest) {
    this.head = head;
    
    if (rest[0] instanceof LinkedList) {
      this.tail = rest[0];
    }
    // roughly equivalent to `rest.any?` in ruby
    else if (rest.some(el => el)) {
      this.tail = new LinkedList(...rest);
    }
    else {
      this.tail = null;
    }
  }

  add(item) {
    return new LinkedList(item, this);
  }

  *[Symbol.iterator]() {
    yield this.head;
    let next = this.tail;

    while (next !== null) {
      yield next.head;
      next = next.tail;
    }
  }
}
```

We can then use our new `LinkedList` class like so:

```javascript
const ll = new LinkedList(0, 1, 1, 2, 3, 5, 8, 13);

for (let value of ll) { 
  console.log(value); // output: 0, 1, 1, 2, 3, 5, 8, 13
}

const [a, b] = ll; // a = 0, b = 1

[...ll].map((num) => console.log(num)); // output: 0, 1, 1, 2, 3, 5, 8, 13
```

## And that's it!

The first time the function is run, we `yield` the current head. Then, as long as there is a tail to read from, we `yield` the head of the list item on the tail. Once we've done that, the iterator is implicitly `done`. In seven lines of code, we've implemented our iterator. Awesome!

Let us know what you think about this blog, or what JavaScript wonders you'd like us to write about on Twitter [@AppSignal](https://www.twitter.com/appsignal)