Understanding the JavaScript For...of Loop

By Orinami Olatunji

What is the For…of Loop?

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 pair 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 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 in 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 recieves 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 which 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:

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) { // TypeError: obj[Symbol.iterator] is not a function
    console.log(value);
}

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 by-pass 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 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);
}
// Outcome:
// 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 object but doesn’t include all objects.

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

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

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

For...of doesn’t considered 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

Summary

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!

Source:: scotch.io