JavaScript Iterable & Iterators

JavaScript Iterable & Iterators

ยท

2 min read

Iterable

Any object is iterable if it has [Symbol.iterator] method which return an iterator object.

So, any object to be iterable it must implement iterable interface.

interface Iterable {
  [Symbol.iterator]() {
    //...
    return Iterator;
  }
}

In simple words, any object is iterable (iter + able meaning able to be iterated) if it contains a method name Symbol.iterator (symbols can also define methods) that returns an Iterator.

Iterator

An iterator object must have method next() which returns an object with properties { value, done }

So, any object to be Iterator it must implement Iterator interface.

interface Iterator {
  next() {
     //...
     return {
        value: <value>,
        done: <boolean>
     };
  };
}

Note: done indicates the end of the iteration and value will be the result extracted from the iteration

How to check if an object is Iterable?

Based on above concepts, we know that an Object to be iterable it must have a property or key [Symbol.iterator] which is a function.

function isIterable(obj) {
  // checks for null and undefined
  if (obj == null) {
    return false;
  }
  return typeof obj[Symbol.iterator] === 'function';
}

Alternatively, we can also use for...of or spread operator [...iterable] to check if some object is iterable or not. If object is not iterable it will throw error

"TypeError: object is not iterable"

Let's try above concepts to create an iterable object literal.

const fruitPrices = {
  apple: '$50',
  orange: '$30'
}

isIterable(fruitPrices); // false
for (const ele of fruitPrices) console.log(ele); // TypeError: fruitPrices is not iterable

We can see fruitPrices is not iterable. Let's convert it into an iterable object.

const fruitPrices = {
  apple: '$50',
  orange: '$30',
  [Symbol.iterator]: function(){
    const objEntries = Object.entries(this);
    return {
    next: function () {
      const isEmpty = objEntries.length === 0;
      return {
          value: objEntries.pop(),
          done: isEmpty
          }
        }
    }
  } 
}

isIterable(fruitPrices); // true

const iterator = fruitPrices[Symbol.iterator]();
iterator.next(); // { value: [ 'orange', '$30' ], done: false }
iterator.next(); // { value: [ 'apple', '$50' ], done: false }
iterator.next(); // { value: undefined, done: true }

for (const ele of fruitPrices) console.log(ele);

Thanks for spending your precious time, have a good day. ๐Ÿ™‚

Did you find this article valuable?

Support Sujeet Agrahari by becoming a sponsor. Any amount is appreciated!