Quick Access

Favorites

No favorites yet

Star your frequently used calculators to access them quickly

Browse Calculators
Saved Color Pairs
JavaScriptJavaScript

Understanding Higher-Order Loops in JavaScript

Avatar for Subhro Kar
Subhro Kar
Published on January 20, 2024

If you're tired of writing repetitive code to iterate over arrays and objects, it’s time to discover the higher-order loops.

Higher-order loops provide an easy and powerful way to work with data collections, making your code clearer, shorter, and easier to maintain.

Unlike traditional loops, higher-order loops are methods that take a callback function and apply it to each element in a collection.

Yes, this is a defining feature of higher-order loops: they accept a function as an argument to process each element in a collection.

So Instead of using traditional for or while loops, we will use high-order loops use functions like map, filter, reduce, and others to handle looping in a more abstract and often more readable way.

Additionally, for...of and for...in loops provide a more straightforward syntax for iterating over values and properties without the need for a callback function.

For Of Loop

The for...of loop is a modern iteration statement in JavaScript that simplifies looping over iterable objects such as arrays, strings, maps, sets, and other objects that implement the iterable protocol. It allows you to traverse all the elements of an iterable without having to worry about the index or the length property.

The for...of loop is a modern iteration statement in JavaScript that simplifies looping over iterable objects such as arrays, strings, maps, sets, and other objects that implement the iterable protocol. It allows you to traverse all the elements of an iterable without having to worry about the index or the length property.

Syntax

1for (variable of iterable) { 2 // statement 3} 4
  • variable: A variable that will be assigned the value of each iterated element.
  • iterable: An object that has iterable properties, like an array, string, set, map, etc.

The for...of loop is particularly useful when you need to iterate over all elements of an array, string, or any other iterable, without the need to access the index or perform specific operations based on the index.

Iterating Over Different Data Types

Iterating Over an Array

1const numbers = [1, 2, 3, 4, 5]; 2for (const number of numbers) { 3 console.log(number); 4} 5// Output: 1 2 3 4 5 6

This code snippet creates an array called numbers containing the values 1, 2, 3, 4, and 5. It then uses a for...of loop to iterate over each element in the numbers array. During each iteration, the current element is assigned to the variablenumber, and then the console.log() function is used to output the value of number to the console. This loop will output each number in the numbers array on a separate line.

Iterating Over a String

1for (const char of message) { 2 console.log(char); 3} 4// Output: H e l l o 5

Iterating Over a Map

Maps are collections of key-value pairs where each key is unique. When iterating over a map, you use the for...of loop along with destructuring to access each key-value pair.

1const userRoles = new Map(); 2userRoles.set("John", "Admin"); 3userRoles.set("Jane", "Editor"); 4userRoles.set("Doe", "Viewer"); 5 6for (const [user, role] of userRoles) { 7 console.log(`${user}: ${role}`); 8} 9// Output: John: Admin 10// Jane: Editor 11// Doe: Viewer 12

Map Characteristics:

  • Unique Keys: Each key in a map must be unique. Adding a key that already exists will overwrite the previous value.
  • Maintained Order: Maps maintain the insertion order of the key-value pairs. The first element inserted will be the first one iterated over, and so on.

Iterating Over a Set

A Set in JavaScript is a collection of unique values. It can hold any type of values, whether primitive or object references.

Characteristics of a Set:

  • Unique Values: Each value must be unique; duplicates are not allowed.
  • Order of Insertion: Maintains the order of element insertion.
  • Iterable: Sets are iterable, allowing you to use loops such as for...of.
1const uniqueNumbers = new Set([1, 2, 3, 4, 5]); 2for (const number of uniqueNumbers) { 3 console.log(number); 4} 5// Output: 1 2 3 4 5 6

Using for...of with the arguments Object

The arguments object is an array-like object accessible inside functions that contain the values of the arguments passed to that function.

Note that it is not a real array, so array methods like forEach or map cannot be directly used on it without converting it to a real array first. Each argument can be accessed using a zero-based index.

1function sum() { 2 let total = 0; 3 for (const num of arguments) { 4 total += num; 5 } 6 return total; 7} 8 9console.log(sum(1, 2, 3, 4)); // Output: 10 10

This code snippet defines a function called sum that calculates the total sum of all the arguments passed to it. It uses a for...of loop to iterate over the arguments object, which contains all the arguments passed to the sum function.

Since the sum function definition does not specify a fixed number of parameters,it can accept a variable number of arguments and it uses the arguments object to access all the arguments passed to the function.

The for...of loop then iterates over these arguments, allowing the function to handle any number of arguments provided when it is called.

Using for...of to iterate on Object

The for...of loop is not directly applicable to plain objects because they are not iterable by default. However, you can still iterate over the properties of an object using alternative methods, such as Object.keys(), Object.values(), or Object.entries(), combined with the for...of loop.

Iterating Over Object Properties Using for...of

  1. Using Object.keys(): Iterates over the keys of the object.
  2. Using Object.values(): Iterates over the values of the object.
  3. Using Object.entries(): Iterates over the key-value pairs of the object.

Examples

Iterating Over Keys

1const user = { 2 name: "John", 3 age: 30, 4 profession: "Developer", 5}; 6 7for (const key of Object.keys(user)) { 8 console.log(key); 9} 10 11// Output: 12// name 13// age 14// profession 15

Iterating Over Values

1const user = { 2 name: "John", 3 age: 30, 4 profession: "Developer", 5}; 6 7for (const value of Object.values(user)) { 8 console.log(value); 9} 10 11// Output: 12// John 13// 30 14// Developer 15

Iterating Over Entries

1const user = { 2 name: "John", 3 age: 30, 4 profession: "Developer", 5}; 6 7for (const [key, value] of Object.entries(user)) { 8 console.log(`${key}: ${value}`); 9} 10 11// Output: 12// name: John 13// age: 30 14// profession: Developer 15

For IN Loop

The for...in loop in JavaScript is used to iterate over the enumerable properties of an object. This includes properties that are inherited through the prototype chain unless those properties are non-enumerable.

To understand the difference between For of and For in loop read the article Understanding JavaScript Loops: for...in vs for...

Syntax

1for (variable in object) { 2 // statement 3} 4
  • variable: A variable that will be assigned the key (property name) of each iterated property.
  • object: The object whose enumerable properties are iterated over.

The for...in loop is particularly useful for iterating over the properties of an object, allowing you to access both the property names (keys) and their values.

Best Practices

Object Check: Ensure you are iterating over objects and not arrays, as for...in is not meant for array iteration (use for...of or array methods like forEach for arrays).

Own Properties Check: Use hasOwnProperty to filter out properties inherited through the prototype chain if needed.

The for...in loop is particularly useful for iterating over the properties of an object, allowing you to access both the property names (keys) and their values.

Avoid with Arrays: Avoid using for...in with arrays due to potential issues with non-integer keys and inherited properties.

Examples

Let's create a plain object representing a car and use the for...in loop to iterate over its properties:

1const car = { 2 make: "Toyota", 3 model: "Corolla", 4 year: 2020, 5 color: "Red", 6}; 7 8for (const key in car) { 9 console.log(`${key}: ${car[key]}`); 10} 11 12//Output 13 14make: Toyota; 15model: Corolla; 16year: 2020; 17color: Red; 18

Iterating Over Object Properties:

Iterating over object properties refers to examining each key-value pair in a JavaScript object. This is commonly done using the for...in loop, which iterates over all enumerable properties of an object, including those inherited through the prototype chain. To restrict iteration to an object's own properties, the hasOwnProperty method is used.

1const user = { 2 name: "John", 3 age: 30, 4 profession: "Developer", 5}; 6 7for (const key in user) { 8 if (user.hasOwnProperty(key)) { 9 // Ensuring it's an own property 10 console.log(`${key}: ${user[key]}`); 11 } 12} 13 14// Output: 15name: John; 16age: 30; 17profession: Developer; 18

Iterating Over Inherited Properties:

When you iterate over inherited properties, you are accessing properties that are not defined directly on the object but are inherited from its prototype. This can be done using the for...in loop. To demonstrate:

1function Person(name, age) { 2 this.name = name; 3 this.age = age; 4} 5 6Person.prototype.profession = "Developer"; 7const john = new Person("John", 30); 8for (const key in john) { 9 console.log(`${key}: ${john[key]}`); 10} 11// Output: 12name: John; 13age: 30; 14profession: Developer; 15

Arrays in JavaScript are best iterated using other methods, such as for...of, forEach(), or traditional for loops, as these provide more predictable outcomes and do not include prototype properties in the iteration. For example:

1const numbers = [1, 2, 3, 4, 5]; 2 3for (const index in numbers) { 4 console.log(index); 5} 6// Output: 7// 0 8// 1 9// 2 10// 3 11// 4 12

If you want to print both the indices and the values, you can combine the for...in loop with the array access:

1const numbers = [1, 2, 3, 4, 5]; 2 3for (const index in numbers) { 4 console.log(`Index: ${index}, Value: ${numbers[index]}`); 5} 6// Output: 7// Index: 0, Value: 1 8// Index: 1, Value: 2 9// Index: 2, Value: 3 10// Index: 3, Value: 4 11// Index: 4, Value: 5 12

Working with Maps

The for...in loop is not suitable for iterating over Maps in JavaScript. Instead, you should use the for...of loop to iterate over Maps. However, if you want to iterate over the keys, values, or entries of a Map, you can use the Map's built-in methods: keys(), values(), and entries(), combined with the for...of loop.

Iterating Over Keys:

1const userRoles = new Map(); 2userRoles.set("John", "Admin"); 3userRoles.set("Jane", "Editor"); 4userRoles.set("Doe", "Viewer"); 5 6for (const key of userRoles.keys()) { 7 console.log(key); 8} 9 10// Output: 11// John 12// Jane 13// Doe 14

Iterating Over Values:

1const userRoles = new Map(); 2userRoles.set("John", "Admin"); 3userRoles.set("Jane", "Editor"); 4userRoles.set("Doe", "Viewer"); 5 6for (const value of userRoles.values()) { 7 console.log(value); 8} 9 10// Output: 11// Admin 12// Editor 13

Iterating Over Entries:

1const userRoles = new Map(); 2userRoles.set("John", "Admin"); 3userRoles.set("Jane", "Editor"); 4userRoles.set("Doe", "Viewer"); 5 6for (const [key, value] of userRoles.entries()) { 7 console.log(`${key}: ${value}`); 8} 9 10// Output: 11// John: Admin 12// Jane: Editor 13// Doe: Viewer 14

Iterating Directly Over the Map (Entries by Default):

You can iterate directly over a Map in JavaScript using a for...of loop. By default, this loop provides each entry as a [key, value] pair:

1const userRoles = new Map(); 2userRoles.set("John", "Admin"); 3userRoles.set("Jane", "Editor"); 4userRoles.set("Doe", "Viewer"); 5 6for (const [key, value] of userRoles) { 7 console.log(`${key}: ${value}`); 8} 9 10// Output: 11// John: Admin 12// Jane: Editor 13// Doe: Viewer 14

forEach Loop

The forEach loop is a method available on arrays and other iterable collections (like Maps and Sets) in JavaScript. It allows you to execute a provided function once for each array element.

The forEach method requires a callback function that will be executed once for each element in the array. This callback function can take up to three arguments:

Syntax

1array.forEach(function (element, index, array) { 2 // statement 3}); 4
  • element: The current element being processed in the array.
  • index (optional): The index of the current element being processed in the array.
  • array (optional): The array that forEach was called upon.

The forEach method is particularly useful when you need to perform a specific action for each element in an array, such as logging values, updating elements, or performing calculations.

Basic Iteration Over an Array:

1const numbers = [1, 2, 3, 4, 5]; 2/* you can write this also 3numbers.forEach(function (item) {}) 4*/ 5numbers.forEach((number) => { 6 console.log(number); 7}); 8 9// Output: 10// 1 11// 2 12// 3 13// 4 14// 5 15

Using Index and Array Parameters:

1const numbers = [1, 2, 3, 4, 5]; 2numbers.forEach((number, index) => { 3 console.log(`Index: ${index}, Value: ${number}`); 4}); 5 6// Output: 7// Index: 0, Value: 1 8// Index: 1, Value: 2 9// Index: 2, Value: 3 10// Index: 3, Value: 4 11// Index: 4, Value: 5 12

Modifying Elements:

1let numbers = [1, 2, 3, 4, 5]; 2numbers.forEach((number, index, arr) => { 3 arr[index] = number * 2; 4}); 5 6console.log(numbers); 7// Output: [2, 4, 6, 8, 10] 8

Working with Maps and Sets

Using forEach with a Map:

1const userRoles = new Map(); 2 3userRoles.set("John", "Admin"); 4 5userRoles.set("Jane", "Editor"); 6 7userRoles.set("Doe", "Viewer"); 8 9userRoles.forEach((value, key) => { 10 console.log(`${key}: ${value}`); 11}); 12 13// Output: 14// John: Admin 15// Jane: Editor 16// Doe: Viewer 17

Using forEach with a Set:

1const uniqueNumbers = new Set([1, 2, 3, 4, 5]); 2uniqueNumbers.forEach((value) => { 3 console.log(value); 4}); 5 6// Output: 7// 1 8// 2 9// 3 10// 4 11// 5 12

Function Passing Techniques

Passing functions to the forEach method is a common practice in JavaScript. You can pass both named and anonymous functions as the callback function for forEach. Here's how you can do it with various examples:

Using Anonymous Functions

You can pass an anonymous function directly to the forEach method.

1const numbers = [1, 2, 3, 4, 5]; 2numbers.forEach(function (number) { 3 console.log(number); 4}); 5// Output: 6// 1 7// 2 8// 3 9// 4 10// 5 11

Using Arrow Functions

Arrow functions provide a concise syntax for writing functions.

1const numbers = [1, 2, 3, 4, 5]; 2numbers.forEach((number) => { 3 console.log(number); 4}); 5 6// Output: 7// 1 8// 2 9// 3 10// 4 11// 5 12

Using Named Functions*

You can define a named function and pass it to the forEach method.

1const numbers = [1, 2, 3, 4, 5]; 2function logNumber(number) { 3 console.log(number); 4} 5 6numbers.forEach(logNumber); 7 8// Output: 9// 1 10// 2 11// 3 12// 4 13// 5 14

Using Named Functions with Additional Parameters

If your named function needs additional parameters, you can create a higher-order function that returns a function with the required parameters.

1const numbers = [1, 2, 3, 4, 5]; 2function createLogger(prefix) { 3 return function (number) { 4 console.log(`${prefix}: ${number}`); 5 }; 6} 7 8const logWithPrefix = createLogger("Number"); 9numbers.forEach(logWithPrefix); 10 11// Output: 12// Number: 1 13// Number: 2 14// Number: 3 15// Number: 4 16// Number: 5 17

Best Practices

When using forEach, keep the following best practices in mind:

  1. Side Effects: Use forEach for performing actions that produce side effects, like modifying elements, logging, or updating the DOM.
  2. Avoid Returns: forEach is not designed for returning values or constructing new arrays. Use map, filter, or reduce for these purposes.
  3. Arrow Functions: Use arrow functions for concise syntax, especially for simple operations.

Conclusion

Passing functions to the forEach loop provides flexibility and reusability in your code. You can use anonymous functions, arrow functions, named functions, and even higher-order functions to achieve different behaviors during iteration. This makes the forEach method a powerful tool for performing operations on arrays and other iterable collections.

Differences Between forEach and Other Loops

  1. NoEarly Exit: Unlike for, for...of, or for...in loops, the forEach method cannot be broken out of using break or return. It will iterate over all elements unless an exception is thrown.
  2. NoReturn Value: The forEach method always returns undefined. It is designed to perform side effects rather than to transform data.
  3. Simplicity: forEach provides a simple and readable way to iterate over arrays and collections, especially when you don’t need to construct new arrays or handle return values.

Working with Array of Objects

When you have an array of objects, you can use the forEach method (or other iteration methods) to iterate over each object in the array and perform operations on its properties. Here are various ways to iterate over an array of objects:

Using forEach Method

Example 1: Logging Each Object

1const users = [ 2 { name: "John", age: 30, profession: "Developer" }, 3 { name: "Jane", age: 25, profession: "Designer" }, 4 { name: "Doe", age: 22, profession: "Tester" }, 5]; 6 7users.forEach((user) => { 8 console.log(user); 9}); 10 11// Output: 12// { name: 'John', age: 30, profession: 'Developer' } 13// { name: 'Jane', age: 25, profession: 'Designer' } 14// { name: 'Doe', age: 22, profession: 'Tester' } 15

Example 2: Logging Specific Properties

1users.forEach((user) => { 2 console.log(`Name: ${user.name}, Age: ${user.age}`); 3}); 4 5// Output: 6// Name: John, Age: 30 7// Name: Jane, Age: 25 8// Name: Doe, Age: 22 9

Using map Method

The map method creates a new array with the results of calling a provided function on every element in the calling array.

1const names = users.map((user) => user.name); 2console.log(names); 3// Output: ['John', 'Jane', 'Doe'] 4

Using for...of Loop

The for...of loop is another way to iterate over an array of objects.

1for (const user of users) { 2console.log(Name: ${user.name}, Age: ${user.age}); 3} 4 5// Output: 6// Name: John, Age: 30 7// Name: Jane, Age: 25 8// Name: Doe, Age: 22 9

Using for Loop

1You can also use the traditional for loop. 2for (let i = 0; i < users.length; i++) { 3 console.log(`Name: ${users[i].name}, Age: ${users[i].age}`); 4} 5 6// Output: 7// Name: John, Age: 30 8// Name: Jane, Age: 25 9// Name: Doe, Age: 22 10

Using reduce Method

The reduce method can be used to accumulate values based on the objects in the array.

Examples:

Summing Ages

1const totalAge = users.reduce((sum, user) => sum + user.age, 0); 2console.log(totalAge); 3 4// Output: 77 5

Combining Iteration with Conditionals

You can combine iteration with conditional statements to filter or process specific objects.

Example: Filtering and Logging Specific Users

1users.forEach((user) => { 2 if (user.age > 24) { 3 console.log(user); 4 } 5}); 6 7// Output: 8// { name: 'John', age: 30, profession: 'Developer' } 9// { name: 'Jane', age: 25, profession: 'Designer' } 10

Conclusion

Iterating over an array of objects can be done using various methods in JavaScript, each with its own advantages:

  • forEach: Simple iteration for performing actions on each element.
  • map: Creates a new array by applying a function to each element.
  • for...of: Clean and readable syntax for iterating over iterable objects.
  • for: Traditional loop that provides full control over the iteration process.
  • reduce: Accumulates values based on the elements in the array.