ES6 Iterators and Generators in JavaScript demystified

Iterators and Generators were introduced in ES6 to make it easier to iterate over different data structures that don’t just include Arrays, String, etc, it gives a common way to iterate over any advanced data structure. Without iterables and iterators, it was difficult to manage the iteration on data for various types of data structures. For example, iterating on an array is different from iterating on an object.

Let’s see, how!

What’s the fuss about these terms?

You would see this concept being discussed around you a lot, especially in interviews. I tried understanding them many times and failed. So, I spent time on it and tried to explain it in the simplest terms. Let’s see one thing at a time!

What are iterators?

An iterator is an object that lets you iterate through collection data one at a time, pausing at each item. Any object that implements the iterator protocol by having a next method that returns a value property and a done property is an iterator.

Iterator Protocol- The iterator protocol defines a standard to produce a sequence of values. This protocol is an object that contains a next() method and this one returns another object with two properties, value and done.

Some Key features-

  • For an entity to be iterable, it should have [Symbol. iterator]() method defined for it.
  • For..of loop works by iterator only, it keeps calling next() method until it reached the end of iterable object.
  • spread operator, Array.from() method, destructuring via an array pattern, etc uses iterators only to work.
  • For..of works only for iterable objects.
  • The for…of statement iterates over values that the iterable object defines to be iterated over.

Iterables

The iterable is an interface that specifies that an object can be used by an iterator if it implements a method that has a key [Symbol. iterator]. If it is built-in, it already has that method, but if it is custom, then you have to implement this custom [Symbol. iterator] method for it.

Some of the built-in iterables in js are :

  • Arrays
  • Strings
  • Maps
  • Sets etc.
  • Objects are not built-in iterables, but you can make them by writing a custom iterator for them.

Let’s see an example of how to define a custom iterator -

// Implementation of custom iterator functionfunction myIterator(array){
let index=0;
return {
next(){

if(index<arr.length){
return {
value:array[index++],
done:false
}
}
else{
return{
value:undefined,
done:true
}
}
}
}
}

Generators

Generator functions create/generate iterables to iterate over. It is a great way to generate iterators. Iterables generated by this function can be iterated over by using for..of loop.

Some Key Features-

  • Generator function uses * with its name while defining it.
  • Instead of return, generators use yield to produce values.
  • One of the use cases is when you want to have an iterable object of a large number and don’t want to store it in memory, then generators come in handy, it generates as and when you want to use it by yielding one value at a time
  • It lets you suspend the function execution and continue later. The Generator function stops the execution after a yield statement, producing a value, and then resume on the next call of next() method.

Let’s see how we can write a generator function-

// Generator function that yields values, one at a time.

function* numberGen(){
yield 1;
yield 2;
yield 3;
}

const gen=numberGen();
gen.next() // it will yield {value:1,done:false} and stop the execution of numberGen
gen.next() // it will again yield a new value as {value:2,done:false} and then stop
  • After encountering a return, generator doesn’t yield more values
function* numberGen(){
yield 1;
yield 2;
return 3; // stops execution after this
yield 4;
}

const gen=numberGen();
gen.next() // {value:1,done:false}
gen.next() // {value:2,done:false}
gen.next() // {value:3,done:true}
gen.next() // {value:undefined,done:true}
  • You can write a generator to produce infinite values without being stuck in an infinite loop.
  • For..of loop to iterate over generator produced object.
// Using for..of loop to iterate over iterable generated  by  a generator

function* numberGen(){
let i=0;
while(true){
yield i++;
}

}

for (const num of numberGen()){
console.log(num)

}

That’s it !!!

Thanks for reading this article, I hope you got something out of it and I’d love to hear your thoughts and feedback!

Listing a few resources if you want to learn more about them-

JavaScript, React and ReactNative Developer