Posts Hidden facts about forEach in JavaScript
Post
Cancel

Hidden facts about forEach in JavaScript

We have been using forEach in JavaScript for a while now, it improves the readability of our code, but what really forEach is? Is forEach a loop in JavaScript?

1: It is not a loop

Yes you heard it, forEach is not a loop, it is a higher order function avilable on Array class which takes a callback as an argument and executes it with each element inside an array in sequential order.

Check out forEach polyfill

1
2
3
4
5
6
7
8
9
if(window.Array && !Array.prototype.forEach){
    Array.prototype.forEach = function(cb, thisArgs){
        var items = this;
        thisArg = thisArg || window;
        for(var i=0; i<items.length; i++){
            cb.call(thisArgs, items[i], i, items);
        }
    }
}

It is clear that forEach is not a loop, it is a function, however it internally uses a for loop to trigger the given callback with each element inside the array.

2: Can’t use break or cotinue statements

There is no way to stop or break a forEach execution other than by throwing an exception, as explained earlier, forEach is not a loop and break or continue statements are not part of forEach semantics, if we use break or continue statemnets inside a forEach function, it will throw a SyntaxError.

3: It expects a synchronous function as callback

forEach does not wait for promises to resolve.

1
2
3
4
5
6
7
8
9
10
11
12
var ratings = [5, 4, 5];
var total = 0;
var total = async function (a, b)
{
  return a + b
}
ratings.forEach(async function(rating) {
  total = await sum(total, rating)
})
console.log(total)
// Expected output: 14
// Actual output: 0

4: return behaves differently

We are familiar with return keyword and quite sure about how it behaves inside a for loop.

Let’s write a function that returns the first even value in the collection.

1
2
3
4
5
6
7
8
9
10
11
12
function firstEven(collection){
    for(var i=0; i<collection.length; i++){
        if(collection[i]%2 === 0){
            return collection[i];
        }
    }
}
var collection = [1,9,4,6,23,9,12];
var evenValue = firstEven(collection);
console.log(evenValue);
// Expected output: 4
// Actual output: 4

It worked as expected!, we got the first even value from the collection.

Let’s re-write the same function with forEach this time.

1
2
3
4
5
6
7
8
9
10
11
12
function firstEven(collection){
    collection.forEach(function(value){
        if(value%2 === 0){
            return value;
        }
    });
}
var collection = [1,9,4,6,23,9,12];
var evenValue = firstEven(collection);
console.log(evenValue);
// Expected output: 4
// Actual output: undefined

it didn’t work this time.

Explanation

A return statement ends function execution and specifies a value to be returned to the function caller.

Let’s see how this definition fits in our scenario.

When the return statement got executed inside the for loop, it immediately ended the function execution (firstEven) and returned the item associated with current iteration and we got first even number from the collection.

In case of forEach, as stated earlier that it executes the callback function with each element in sequential order, when return statement got executed inside a callback, it immediately ended the execution of that callback and returned the value, however callback function will keep on executing for rest of the array elements, and because we are not returning any value from the firstEven function explicitly, it will return the default value which is undefined.

Updated Apr 10, 2020 2020-04-09T20:54:17+00:00
This post is licensed under CC BY 4.0