Since 2015, JavaScript has improved immensely.
It’s much more pleasant to use it now than ever.
In this article, we’ll look at the for-of loop.
The for-of
Loop
The for-of loop lets us replace the for-in loop and forEach
with one loop.
It can also be used to iterate over any iterable object.
For example, we can use the for-of loop to loop through an array by writing:
const arr = [1, 2, 3];
for (const x of arr) {
console.log(x);
}
We have an arr
array and we loop through it with the for-of loop.
x
is the array entry we’re iterating through.
break
and continue
also work inside for-of loops.
For example, we can write:
const arr = [1, 2, 3];
for (const x of arr) {
if (x === 2) {
break;
}
console.log(x);
}
or:
const arr = [1, 2, 3];
for (const x of arr) {
if (x === 2) {
continue;
}
console.log(x);
}
We can still use break
to stop the loop.
And we can use continue
to skip to the next iteration.
Also, it works with iterable object entry destructuring.
For example, we can write:
const arr = [1, 2, 3];
for (const [index, element] of arr.entries()) {
console.log(index, element);
}
We call the arr.entries()
method which returns an array with arrays of the index and the element for the index as the entries.
The for-of loop also works with other kinds of iterable objects.
For example, we can use it to iterate through maps.
We can write:
const map = new Map([
[1, 'foo'],
[2, 'bar'],
]);
for (const [key, value] of map) {
console.log(key, value);
}
We create the Map
instance and loop through it with the for-of loop.
We destructure each entry with the array with key
and value
.
And run console.log
method to log the item.
The for-of loop only works with iterable values.
This means that we need to convert plain objects to iterable objects to make it work with the for-of loop.
For example, if we have an object with the length
property and the indexes as keys, we’ve to convert it to an array with Array.from
.
This means if we write:
const arrayLike = {
length: 2,
0: 'foo',
1: 'bar'
};
for (const x of arrayLike) {
console.log(x);
}
We’ll get the ‘Uncaught TypeError: arrayLike is not iterable’ error.
To fix this, we’ve to use the Array.from
method:
const arrayLike = {
length: 2,
0: 'foo',
1: 'bar'
};
for (const x of Array.from(arrayLike)) {
console.log(x);
}
Array.from
converts the object to an array so we can use the returned array with the for-of loop.
const vs var in Iterable Variables
Since for-of loop creates a fresh binding in each iteration, we can use const
to declare our loop variable in the loop head.
This works as long as we don’t reassign the value in the loop body.
For instance, we can write:
const arr = [];
const orig = ['foo', 'bar', 'baz'];
for (const elem of orig) {
arr.push(() => elem);
}
console.log(arr.map(f => f()));
The console log gives us [“foo”, “bar”, “baz”]
since we const
variables are confined within the block.
let
works the same way as const
, but we can reassign it to a value in the loop block.
On the other hand, if we use var
, we’ll get different results.
For instance, if we have:
const arr = [];
const orig = ['foo', 'bar', 'baz'];
for (var elem of orig) {
arr.push(() => elem);
}
console.log(arr.map(f => f()));
Then we get [“baz”, “baz”, “baz”]
This is because a var
variable is also available outside the block.
So when we run the functions we pushed to arr
, elem
will be 'baz'
.
Therefore, we eliminate confusion by not using var
.
Conclusion
for-of loop provides us with many conveniences with iteration.