Categories
Modern JavaScript

Best of Modern JavaScript — Iteration

Spread the love

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at JavaScript iterable objects.

Speed of the Iteration Protocol

The speed of the iteration protocol has been taken into account when this is created.

Memory management is fast when managing small objects.

JavaScript engine optimization iteration so that no intermediate objects are allocated.

Reuse the Same Iterable Object

We can use iterable multiple times.

So we can write:

const results = [];
const iterator = [1, 2, 3][Symbol.iterator]();

while (!(val = iterator.next()).done) {
  results.push(val);
}

We get the iterator from the array.

And then we called it with our while loop to get the results.

Iteration

There’re rules that govern the JavaScript iteration protocol.

There are some rules for the next method.

As long as the iterator is returning a value next , returns an object with the value property.

And done will be false .

So we have:

{ value: x, done: false }

After the last value is iterated over, next should return an object whose property done is true .

Iterables that Return Iterators

Iterables can return fresh iterators or return the same iterator.

If they return fresh iterators, then each ones return values from the start.

So if we have something like and array and we use:

function getIterator(iterable) {
  return iterable[Symbol.iterator]();
}

to get the iterator, then we can compare them to see if they return the same iterator.

For instance, if we have:

const arr = ['a', 'b'];
console.log(getIterator(arr) === getIterator(arr));

Then the expression would log false .

This means even though the array is the same, they return the same iterator.

Other iterables like generators return the same iterator each time.

If we have generator objects, we return the same generator each time it’s called:

function* genFn() {
  yield 'foo';
  yield 'bar';
}

const gen = genFn();
console.log(getIterator(gen) === getIterator(gen));

The genFn is a generator function that returns a generator,

And when we get the iterator from the generator, we get the iterator from it and compare them and the expression logs true .

So the same generator has the same iterator.

We can iterate over a fresh iterator multiple times.

For instance, we can write:

const arr = ['foo', 'bar', 'baz'];

for (const a of arr) {
  console.log(a);
}

for (const a of arr) {
  console.log(a);
}

to loop through the same array twice.

On the other hand, if we have a generator:

function* genFn() {
  yield 'foo';
  yield 'bar';
}
const gen = genFn();

for (const a of gen) {
  console.log(a);
}

for (const a of gen) {
  console.log(a);
}

then we only loop through it once even if we have 2 loops.

Closing Iterators

There’re 2 ways that an iterator can be closed.

An iterator can be closed with exhaustion or closing.

Exhaustion is when the iterator returned all the iterable values.

Closing is done by calling return in the iterator function.

When we call return , then next won’t be called.

return is an optional method.

Not all iterators have it.

Iterators that have a return call is called closable.

return should only be called if an iterator hasn’t exhausted.

This can happen if we loop through the for-of loop with break , continue , return or throw .

return should produce an object that returns { done: true, value: x } .

Conclusion

Iterable objects can have different variations.

They can return a single iterator or multiple instances.

They can also be closable.

Leave a Reply

Your email address will not be published.

If you like the content of this blog, subscribe to my email list to get exclusive articles not available to anyone else.