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.
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:
Hum, ok. But what is an Iterator object? Hope it is not defined in terms of an Iterable!
That is a relief! But what the hell is an IteratorResult?
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.
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.
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.
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.