fullstackpilot Logo
JavaScript forEach js loop javascript for each loop js foreach

JavaScript forEach - How to loop through the array in JavaScript properly?

Martin Milo
By on

JavaScript forEach is one of the essential functions you can use to loop through the array. There are various ways how to loop through the array and array-like objects thanks to rich JavaScript semantics.

Table of Contents

JavaScript forEach - performance concerns

I've seen the following questions multiple times and been asked on it by junior devs - But isn't forEach slower than the old fashioned for loop?

You're right on that. But using forEach method to loop through an array has several benefits, such as:

  • no need to maintain an explicit counter as with for loop
  • better readability (it's much shorter than writing the for loop construct, therefore simplicity)
  • and finally, by using the method, we can greatly reduce the risk of off-by-one error

And if you're worried about the runtime cost, in 99% of the cases you don't need to be. Unless you're doing something very unusual, you'd be saving microseconds.

JavaScript forEach - how to use it

Let's have a look at how to use the forEach array method with some examples.

The forEach method accepts a callback function, and optionally, we can pass thisArg (which will be used as this when executing the callback). The callback is called once for each item in an array in ascending order.

Anonymous function

const avengers = ['Thor', 'Iron man', 'Hulk'];
// We passed an anonymous function as a callback to forEach
avengers.forEach(function (avenger) {
console.log(avenger);
});
// -- 👇 console.log output --
// Thor
// Iron man
// Hulk

You can also rewrite the anonymous function if you want to use the ES6 arrow syntax:

avengers.forEach((avenger) => {
console.log(avenger)
});

Callback as non-anonymous function

Although not as common, we can declare the callback as non-anonymous function. It's useful if the callback needs to be reused in our code.

const avengers = ['Thor', 'Iron man', 'Hulk'];
// This function probably won't be needed anywhere else
// but let's pretend it would be
function displayInLog(avenger) {
console.log(avenger);
}
avengers.forEach(displayInLog);
// ☝️ is shorthand of:
// avengers.forEach((avenger) => displayInLog(avenger));

Regardless of whether the callback is anonymous or not, JavaScript executes the callback for every item in the array. In the last example, iterated item (in our case avenger) is passed as a first parameter to the callback implicitly.

Iterating with index

Callback we pass to forEach has two more optional parameters. First of the optional parameters is the index.

const avengers = ['Thor', 'Iron man', 'Hulk'];
avengers.forEach(function (avenger, index) {
console.log(`${index + 1}. avenger is ${avenger}`);
});
// -- 👇 console.log output --
// 1. avenger is Thor
// 2. avenger is Iron man
// 3. avenger is Hulk

Iterating with array (self)

Second optional parameter we can pass to the callback is the array itself. Why would you need to access the array if you already have the array which you're trying to loop through? You usually won't. But there is one good example in which you might want to.

Let's pretend that we don't know what the array contains, nor we know it's length.

// We pretend that the data comes from the API
// and we don't know it's length
const avengers = ['Thor', 'Iron man', 'Hulk'];
// Plus we need to filter the data
avengers
.filter((avenger) => avenger !== 'Thor')
.forEach((avenger) => {
// Eh, so what's the array's length now?
});

We can console.log each avenger in the forEach but I among many others find myself doing the following:

const filtered = avengers.filter((avenger) => avenger !== 'Thor')
console.log(filtered.length);
// -- 👇 console.log output --
// 2

We assigned filtered array to the variable, so we can log it down below, before we loop through with forEach. This actually happens quite often.

If the code fails at certain point in this chain, I tend to look at how array looks like in specific step. But rewriting the code, and assigning variable just to do that is just annoying, and too much work.

Second optional callback param (self) to the rescue.

avengers
.filter(avenger => avenger !== 'Thor')
.forEach((avenger, index, self) => {
console.log(self.length);
});
// -- 👇 console.log output --
// 2
// 2

We were able to log the length of the array after filtering without the need of extra variable just for purpose of logging. Pretty cool, isn't it?

Loop through array-like objects

Array-like object are topics on their own, so let's just jump on the examples. If you're working in a browser environment with JavaScript, the most common array-like object you probably encounter is a NodeList - you can get it by trying document.querySelectorAll('p'). You may choose to get different element, not necessarily a paragraph.

While you can now use forEach to iterate over the NodeList, it wasn't always the case. Let's now forget about NodeList and have a quick look on the example:

const avengersInArrayLikeObject = {
"0": "Thor",
"1": "Iron man",
"2": "Hulk",
"length": 3
};

Now in order to iterate over the avengersInArrayLikeObject, we can't call forEach directly. We have couple of options:

// Create new shallow copy of the Array instance from an array-like object
Array.from(avengersInArrayLikeObject).forEach(...);
// We can call slice method
Array.prototype.slice.call(avengersInArrayLikeObject).forEach(...);
// We can call forEach indirectly by using a call method
Array.prototype.forEach.call(avengersInArrayLikeObject, callback);

Conclusion

The forEach array method is very efficient way to loop through them all without breaking, and has relative benefits over the classical for loop. As mentioned before, if your performance-wise concern is that the callback function is invoked for each item in array, in most of the cases there's nothing to worry about.

You can also put side-effects in the callback you pass to forEach but keep in mind that under normal circumstances you can't break the iteration. When an early break from loop is required, perhaps you can loop through the array with classical approach.

There are also several other useful array methods defined by ES5, such as:

I'll link these as soon as I cover them in the separate article. Consider reading up on them, as if you don't you may end up reinventing a method that already exists. For instance some and every are not as well-known as the other array methods.

What is your most preferred way to loop through an array? Feel free to share a comment down below.

Share: