Tutorial

Understanding the JavaScript For...of Loop

JavaScript
This tutorial is out of date and no longer maintained.

Introduction

The for...of statement creates a loop that iterates over iterable objects. For...of loop was introduced in ES6 to be an alternative to both for...in and forEach() and supports the new iteration protocol. For..of lets you loop over data structures that are iterable such as Arrays, strings, Maps, Sets, and more.

Syntax

for (variable of iterable) {
  statement
}
  • variable - For every iteration, the value of the property is assigned to the the variable.
  • iterable - An object which has enumerable properties and can be iterated upon.

Use Cases

Let’s explore some use cases.

Arrays

Arrays are simply list-like objects. Array prototype has various methods that allow operations to be performed on it such as mutation and traversing operations. Here’s a for...of operation on an array:

array-example.js
const iterable = ['mini', 'mani', 'mo'];

for (const value of iterable) {
  console.log(value);
}
Output
mini mani mo

The result is a print-out of every value in the iterable array.

Demo: https://jsbin.com/dimahag/edit?js,console

Map

The Map object holds key-value pairs. Objects and primitive values can be used as either a key or a value. A Map object iterates through elements based on how it was inserted. In order words, for...of loop returns an array of key-value pairs for each iteration.

map-example.js
const iterable = new Map([['one', 1], ['two', 2]]);

for (const [key, value] of iterable) {
  console.log(`Key: ${key} and Value: ${value}`);
}
Output
Key: one and Value: 1 Key: two and Value: 2

Demo: https://jsbin.com/lofewiw/edit?js,console

Set

The Set object allows you to store unique values of any type, which could be primitive values or objects. Set objects are simply collections of values. Iteration on the elements of a Set is based on insertion order. A value in the Set may only occur once. In order words, if you create a set that has the same element more than once, it is still considered as a single element.

set-example.js
const iterable = new Set([1, 1, 2, 2, 1]);

for (const value of iterable) {
  console.log(value);
}
Output
1 2

Even though we have a set that has multiple 1’s and 2’s, we have the output as just 1 and 2.

Demo: https://jsbin.com/fajozob/edit?js,console

String

Strings are used to store data in text form.

string-example.js
const iterable = 'javascript';

for (const value of iterable) {
  console.log(value);
}
Output
"j" "a" "v" "a" "s" "c" "r" "i" "p" "t"

Here, iteration is performed on a string and the character on each index is printed out.

Demo: https://jsbin.com/rixakeg/edit?js,console

Arguments Object

Think of an argument’s object simply as an Array-like object corresponding to the arguments passed to a function. Here’s a use case:

arguments-example.js
function args() {
  for (const arg of arguments) {
    console.log(arg);
  }
}
args('a', 'b', 'c');
Output
a b c

You might be wondering, what is going on?! As I said earlier on, arguments receives any argument passed into the args() function when the function is called. So, if we pass 20 arguments to the args() function, we have 20 arguments printed out.

Demo: https://jsbin.com/ciqabov/edit?js,console

Generators

Generators are functions that can be exited and later re-entered.

generator-example.js
function* generator(){
  yield 1;
  yield 2;
  yield 3;
};

for (const g of generator()) {
  console.log(g);
}
Output
1 2 3

The function* defines a generator function, which returns a Generator object. For more on Generators, check here.

Demo: https://jsbin.com/faviyi/edit?js,console

Closing Iterators

JavaScript offers four known methods of terminating a loop execution namely: break, continue, return and throw. Let’s look at an example:

closing-iterators-example.js
const iterable = ['mini', 'mani', 'mo'];

for (const value of iterable) {
  console.log(value);
  break;
}
Output
mini

In this example, we use the break keyword to terminate the loop after one execution and only mini gets printed out.

Demo: https://jsbin.com/tisuken/edit?js,console

Plain objects are not iterable

For...of loop only works with iterables. Plain objects are not iterable. Let’s have a look:

const obj = { fname: 'foo', lname: 'bar' };

for (const value of obj) {
    console.log(value);
}
TypeError: obj[Symbol.iterator] is not a function

Here we define a plain object obj and when we try the for...of operation on it, we get an error TypeError: obj[Symbol.iterator] is not a function.

Demo: https://jsbin.com/sotidu/edit?js,console

We can bypass this by converting an array-like object to an Array. The object would have a length property and its element would have to be indexed. Let’s look at an example:

object-example.js
const obj = { length: 3, 0: 'foo', 1: 'bar', 2: 'baz' };

const array = Array.from(obj);
for (const value of array) {
    console.log(value);
}
Output
foo bar baz

The Array.from() method creates a new Array instance from an array-like or iterable object.

Demo: https://jsbin.com/miwofin/edit?js,console

For…of vs For…in

The for...in loop will iterate over all the enumerable properties of an object.

for-in-example.js
Array.prototype.newArr = () => {};
Array.prototype.anotherNewArr = () => {};
const array = ['foo', 'bar', 'baz'];

for (const value in array) {
  console.log(value);
}
Output
0 1 2 newArr anotherNewArr

For...in doesn’t only enumerate the array declaration above, it also looks for inherited non-enumerable properties from the constructor’s prototype, in this case, newArr and anotherNewArr and prints them out also.

Demo: https://jsbin.com/quxojof/edit?js,console

For...of is more specific to collections such as arrays and objects but doesn’t include all objects.

Any element that has the Symbol.iterator property is iterable.

Array.prototype.newArr = () => {};
const array = ['foo', 'bar', 'baz'];

for (const value of array) {
  console.log(value);
}
Output
foo bar baz

For...of doesn’t consider the non-enumerable properties of the constructor’s prototype. It simply just looks for the enumerable properties and prints it out.

Demo: https://jsbin.com/sakado/edit?js,console

Conclusion

Understanding the usage of For...of loop can save you a lot of time during development. Hopefully, this article helped you understand and write better loop constructs in your JavaScript development. Happy coding!

Creative Commons License