Explanation about Iterators and Generators in Javascript ES6

Madasamy M
5 min readOct 10, 2018

--

In JavaScript, we need to Iterate a data for binding with UI right?? so Processing each of the items in a collection is a very common operation. JavaScript provides a number of ways of iterating over a collection, from simple for loops to map() and filter(). So Iterators and Generators bring the concept of iteration directly into the core language and provide a mechanism for customizing the behavior of for...of loops.

In easy way to Iterate data in Javascript is Iterators and generators, those are implemented in ES6.

Things you need to know about,

What are Iterators and Iterables?

How Iterators works?

What are Generators?

How Generators Works?

Usecase of Generators?

Let me answer question one by one !!!

What is Iterables and Iterators?

ES6 introduces a new mechanism for traversing data: iteration. Two concepts are central to iteration:

  • An iterable is a data structure that wants to make its elements accessible to the public. It does so by implementing a method whose key is Symbol.iterator. That method is a factory for iterators.
  • An iterator is a pointer for traversing the elements of a data structure (think cursors in databases)

Iterable values in Javascript

The following values are iterable:

  • Arrays
  • Strings
  • Maps
  • Sets
  • DOM data structures (work in progress)

Plain objects are not iterable.

The idea of iterability is as follows.

  • Data consumers: JavaScript has language constructs that consume data. For example, for-of loops over values and the spread operator (...) inserts values into Arrays or function calls.
  • Data sources: The data consumers could get their values from a variety of sources. For example, you may want to iterate over the elements of an Array, the key-value entries in a Map or the characters of a string.

Practically not possible to create consumers for all data sources, that’s the reason ES6 introduces Interface Iterable.

How Iterators Works?

In ES6, They have standardized the Iterables as, below sample code,

Example code of an Iterable implementation

const Iterable = {
[Symbol.iterator]() {
let step = 0;
const iterator = {
next() {
step++;
if (step === 1)
return { value: 'Example', done: 'false' }
else if (step === 2)
return { value: 'for', done: 'false' }
else if (step === 3)
return { value: 'Iterator', done: 'false' }
return { value: undefined, done: 'true' }
}
};
return iterator;
}
}
var iterator = Iterable[Symbol.iterator]();
iterator.next() // {value: 'Example', done: 'false'}
iterator.next() // {value: 'for', done: 'false'}
iterator.next() // {value: 'iterator', done: 'false'}
iterator.next() // {value: undefined, done: 'false'}

used the name Symbol.iterator. Symbols offer names that are unique and cannot clash with other property names. Also, Symbol.iterator will return an object called an iterator. This iterator will have a method called nextwhich will return an object with keys value and done.

The following ES6 language constructs make use of the Iterable:

  • Destructuring via an Array pattern
  • for-of loop
  • Array.from()
  • Spread operator (...)
  • Constructors of Maps and Sets
  • Promise.all(), Promise.race()
  • yield*

What are Generators?

You can think of generators as processes (pieces of code) that you can pause and resume while executing that particular code :

function* func() {
// (A)
console.log('First');
yield;
console.log('Second');
}

Note the new syntax: function* is a new “keyword” for generator functions (there are also generator methods). yield is an operator with which a generator can pause itself. Additionally, generators can also receive input and send output via yield.

sample code using generator:

function* increment(i) {
yield i + 1;
yield i + 2;
}
var obj = increment(10);console.log(obj.next()); \\{value: 11, done: false}
console.log(obj.next()); \\{value: 12, done: false}
console.log(obj.next()); \\{value: undefined, done: true}

There are four kinds of generators:

  1. Generator function declarations:
function* genFunc() { ··· }
const genObj = genFunc();

above we are declaring generator as a function,

2. Generator function expressions:

const genFunc = function* () { ··· };
const genObj = genFunc();

3. Generator method definitions in object literals:

const obj = {
* generatorMethod() {
···
}
};
const genObj = obj.generatorMethod();

4. Generator method definitions in class definitions

class MyClass {
* generatorMethod() {
···
}
}
const myInst = new MyClass();
const genObj = myInst.generatorMethod();

Above these are the way to declare a generator function.

Usecase of Generators:

There are many use cases for generators ,

  1. simpler asynchronous code

we can execute simple asynchronous block of code.

2. receiving asynchronous data using generators

ES8 will have async functions(async/await) which are internally based on generators. With them, the code looks like this:

async function fetchJson(url) {
try {
let request = await fetch(url);
let text = await request.text();
return JSON.parse(text);
}
catch (error) {
console.log(`ERROR: ${error.stack}`);
}
}

3. Implementing Iterables

you could have used Object.entries() method for iterating over object, this Object.entries() method implementation should be like this using generators,

function* objectEntries(obj) {
const propKeys = Reflect.ownKeys(obj);

for (const propKey of propKeys) {
// `yield` returns a value and then pauses
// the generator. Later, execution continues
// where it was previously paused.
yield [propKey, obj[propKey]];
}
}

The above function returns an iterable over the properties of an object, one [key, value] pair per property, The objects returned by generators are iterable,using that iterable we can get next yield of [key,value] pair use of for-of loop,

The following code use that Object.entries() method,

const user= { name: 'raja', age: 25};
for (const [key,value] of objectEntries(user)) {
console.log(`${key}: ${value}`);
}
// Output:
// name: raja
// age: 25

How exactly objectEntries() works is explained in a dedicated section. Implementing the same functionality without generators is much more work.

conclusion:

As far we had discussed, we have learned about Iterables,Iterators and generators.

Thanks for reading !!!.

My other posts are !

--

--

Madasamy M

FullStack Developer at AX2 Technologies pvt Ltd, Working in Web Application Development, Chatbot Development