Iterable protocol~ Basics ~

Iterable protocol

The iterable protocol is underrated. I don't see people using it, which makes me sad because it's a wonderful instrument. It defines how we loop over a specific object. Or in other words, it allows us to create custom iterating behavior. We have to create a property called @@iterator (Symbol.iterator is a shortcut for this key). That property must equal a zero-argument function that returns an object matching the iterable protocol. Here is an example:

const user = {
  data: ["JavaScript", "HTML", "CSS"],
  [Symbol.iterator]: function () {
    let i = 0;
    return {
      next: () => ({
        value: this.data[i++],
        done: i > this.data.length,
      }),
    };
  },
};
for (const skill of user) { console.log(skill); }

The protocol requires that we return an object with a next method. That method should result in another object that has value and done fields. The value could be anything, and done is a boolean that indicates whether the iteration is over.

Notice, in the example above, how user is not an array, but we can use it as such. That is because we defined a custom iterator. The script outputs "JavaScript", "HTML" and "CSS" (in that order).

This feature comes in handy if we have complex data structures and we want to access deeply nested properties. I like to use the iterable protocol to facilitate the destructing of my objects.

const user = {
  name: { first: 'Krasimir', last: 'Tsonev' },
  position: 'engineer',
  [Symbol.iterator]: function () {
    let i = 0;
    return {
      next: () => {
        i++;
        if (i === 1) {
          return { value: `${this.name.first} ${this.name.last}`, done: false };
        } else if (i === 2) {
          return {value: this.position, done: false };
        }
        return { done: true }
      }
    }
  }
}
const [name, position] = user;
console.log(`${name}: ${position}`); // Krasimir Tsonev: engineer

By definition, we can destruct every iterable object. And if our objects are not iterable, we can make them so by using the technique above - defining an iterable protocol.