for/of and for/in loop in JavaScript

for/of and for/in loop in JavaScript

Hey there 👋 ,The for loop in javascript has multiple flavours. Let us understand these in this post.
There are mainly three kinds of for loops -

  • for
  • for/of
  • for/in

for is one of the most common construct of the for loop which is just like the other programming languages and most of you would already be familiar with its usage. However with ES6 two new constructs of for loop for/of and for/in has been introduced. Let us go through these new constructs and understand its usage and behavior.

for/of

The for/of loop works with iterable objects. The data structures like the Strings, Arrays, Sets and Maps are iterable in JavaScript. These data structures contains elements that can be iterated using a for/of loop.

Syntax

for(let [element of the iterable object] of [expression that evaluates to an iterable object]){
    //body of the loop
}

Usage with String

Examples

//Example of for/of with String
let name = "John"
for(let letter of name)
{
    console.log(letter)
}

Output
J
o
h
n

In the above example the string variable name evaluates to an iterable object and hence we can iterate over the name with for/of and with each iteration we can access each letter of the name.

Usage with an Array

Now lets use the spread operator of ES6 to convert this name variable into an array and iterate over the Array using the for/of loop.

let name = "John"
let arrLetters = [...name] // This would return ['J', 'o', 'h', 'n']
//Example of for/of with an Array
for(let letter of arrLetters)
{
    console.log(letter)
}

Output
J
o
h
n

Usage with Set

We will now convert the name variable to a Set and iterate over it using a for/of loop and check the result.

//declaring the string variable "name"
let name ="John"
//converting the string variable "name" to a Set.
let setName = new Set(name)
console.log(setName) //Set(4) {'J', 'o', 'h', 'n'}
//iterating over the new created set
for(let letter of setName)
{
    console.log(letter)
}

Output
J
o
h
n

Usage with Map

Lets create a Map and try out the for/of with a Map data structure. A Map object contains key-value pairs in the same order in which it was inserted. It can have any object or primitive type as the key or value.

//declaring a Map
const mapNames = new Map();
//adding values to Map
mapNames.set("name1","John")
mapNames.set("name2","Mary")
mapNames.set("name3","Ben")

console.log(mapNames); //Map(3) {'name1' => 'John', 'name2' => 'Mary', 'name3' => 'Ben'}

//iterating over the Map
for (const mapElement of mapNames) {
console.log(mapElement)
}

Output
(2) ['name1', 'John']
(2) ['name2', 'Mary']
(2) ['name3', 'Ben']

Notice that that unlike the String , Array and Set the output of the map is itself an array with each array element consisting of the key-value pair.

We can destructure the array elements in the for/of loop and access the key and the value individually

//declaring a Map
const mapNames = new Map();
//adding values to Map
mapNames.set("name1","John")
mapNames.set("name2","Mary")
mapNames.set("name3","Ben")

console.log(mapNames); //Map(3) {'name1' => 'John', 'name2' => 'Mary', 'name3' => 'Ben'}

//iterating over the Map
for (const [key,value] of mapNames) {
//log the keys
console.log(key)
//log the values
console.log(value);
}

Output

Map(3) {'name1' => 'John', 'name2' => 'Mary', 'name3' => 'Ben'}
name1
John
name2
Mary
name3
Ben

Note that we can also access the keys and the values from the map objects and iterate over only the keys or the values.

mapNames.keys()    // {'name1', 'name2', 'name3'}
mapNames.values()  // {'John', 'Mary', 'Ben'}

Usage with an Objects

Objects are not iterable with a for/of loop by default. But if we want to iterate over an object with a for/of loop we can leverage the methods inside an object to retrieve the property name and property value and iterate over the same.
The for/of loop can be used with an object using the following methods -

  1. Object.keys(object)
  2. Object.values(object)
  3. Object.entries(object)

Object.entries() just like the Map object gives an array of arrays with each element being a pair of the property name and property value and could be used with the destructuring syntax.

Important In general any data structure that has the iterator method "Symbol.iterator()" which generates the iterable object can be iterated using a for/of loop.

for/in

The for/in loop looks similar to the for/of loop but unlike for/of loop for/in does not need an iterable object to work rather it works with any object. The for/in loop has been in JavaScript from the very beginning while the for/of loop was introduced in ES6.
for/in loop is used to iterate over the property names of the object that is specified after the in keyword.

Syntax

for (key in object) {
    //body of the loop
}

The key key can be any expression that we can write on the left hand side of the assignment operator. It can be a constant or variable or anything that can be assigned some value to. But the important point to note over here is that the value to be assigned to the key would the property name of the object. This property name can then be used inside the body of the loop to extract the value of the property. The object present after the in keyword could be either an object directly or an expression that evaluates to an object. When the JavaScript interpretor first encounters the for/in contruct it first evaluates the object and skips the loop if the evaluation leads to a null or undefined value. If the evaluation leads to an object it iterates through all the enumerable properties in the objects and assigns the property name to the key. This means that the key would be assigned different values in each iteration depending on the number of enumerable properties in the object.

The properties added on an object by our code is enumerable by default. Hence the user defined properties are always iterated by the for/in loop however there are techniques by which the user defined properties can be turned to non-enumerable property.
The built-in methods defined by the JavaScript Standard library available on the objects may be enumerable or non enumerable.
We can check if the property is enumerable or not by calling the propertyIsEnumerable() method on the object. For example if we want to check if the "toString()" method available on every object is enumerable or not by using the below code -

Object.propertyIsEnumerable("toString") 

Output
false

Since the built-in property toString() is non enumerable if is not iterated through the for/in loop.

Now since the for/in loop iterates through the objects own property as well as all the enumerable built-in property we may have performance issues while iterating over the large object.
To avoid this situation we can first check if the property is the objects own property and skip iterating over them.

for(let property in object)
{
    if(object.hasOwnProperty(property)){
        //execute the code for the objects own property
    }
}

for/in is mostly useful for debugging purposes and we can use the various methods available on an object to get the own property names, keys , as an array and we can and use a for/of loop instead as an alternative to the for/in loop.

  • Object.keys()
  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Reflect.ownKeys()

Conclusion

I hope you have understood the usage and behavior of the for/of and for/in loop.
Thank you for reading this post and see you in the next post.
Happy Coding.💻

Book Recommendation

I would recommend you to refer to the book JavaScript - The Definitive Guide by David Flanagan for an in-depth understanding of the JavaScript Language.