forEach vs map, which one to use and what cases?

8Responses

Write your response…

This answer has received 2 appreciations.

From the functional programming point of view:

forEach is a consumer operation and hence the terminal operation in the stream so you can only consume the input but cannot generate the output and pass it to next stream. Programatically, your forEach code block should not contain return statement.

ex:

arr.forEach( val => {
//... logic to use val
// but no return statement
});

map is a transform operation in the stream i.e., you take X as the input and produce Y as the output and optionally pass it to the next stream. Programatically, code block inside map operation must return some value.

ex (purposely written with brevity for syntactical understanding) :

const numArr = [1, 2, 3, 4, 5];

// first example
const numDoubledArr = numArr.map( num => {
        return num + num; // transformation 
    });

// second example
numArr
    .map( num => {
        return num + num; // transformation
    })
    .forEach( doubledNum => {
       console.log('Doubled Number: ', doubledNum);
    });

My intention was to explain the possible use-cases for map and forEach operator and addition of two numbers was the simplest explanation for transformation but not to generate the sum of all numbers of an array :)

Write a reply...

This answer has received 1 appreciation.

It would be more clear if you share the linter error you get.

forEach will iterate over the elements (without visiting new elements added at runtime) of an array and returns undefined.

If you need to return a value AND a new array, you use map. Since it returns another array, chaining map will be easier.

Write a reply...

forEach is a mutating function which changes the value directly. Hence no return statement in iterator. And also forEach doesn't return any value.

map is non-mutating and pure function. So it's iterator needs to return a value for every iteration, otherwise it will go as nothing received, hence null . In the end, map returns a new transformed array, leaving the input array intact.

Examples:

const input = [1,2,3];

// Map:
const power = input.map(num => num * num);
console.log(power); // [1, 4, 9]
console.log(input); // [1, 2, 3]

// ForEach:
const increasedByTwo = input.forEach(num => num += 2);
console.log(increasedByTwo); // undefined
console.log(input); // [3, 4, 5]

P.S. Shameless effort to promote; as google was not consulted, let me lead you to a good article written by me 😉 time2hack.com/2017/10/iterating-data-with-m..

I think I said it wrong, it will not return anything; though you understood it correctly 👍

Not returning anything will fill null for that specific iteration. If the iterator function will not return anything for any iteration; you will have a list of null with you in the end.

Write a reply...

As far as my knowledge of Functional Programming goes, the map operator can make use of multiple threads and calculate the values faster as compared to forEach which processes one value at a time.

I am not sure, but this talk by Anjana Vakil covers this very point that you have doubts about.

youtube.com/watch?v=e-5obm1G_FY

Write a reply...

I think the other answers so far even when accurate do not break it down simple enough.

Array.map When your result set is an array containing existing values that your callback returns boolean true.

Array.foreach When you want to just loop through all the elements with a callback returning nothing.

An even simpler way to explain it would be to show some code for polyfilling them in older browsers since BOTH are actually relatively new and don't exist in legacy IE. Personally I always find it easier to understand a function/method if I can see a work-alike code.

Array.prototype.foreach = function(callback) {
    for (var i = 0, iLen = this.length; i < iLen; i++)
        callback(this[i]);
}

Array.prototype.map = function(callback) {
    var result = [];
    for (var i = 0, iLen = this.length; i < iLen; i++)
        if (callback(this[i])) result.push(this[i]);
    return result;
}

That is what they actually DO. Mind you I gutted out the "throws" for if it is null or not array, and the oddball corner case fixes.

Side note, I've seen some people suggesting doing Array.from(myNodeList).forEach instead of doing "for" on a nodeList (like the result from getElementsByTagName) -- whist this SEEMS simpler beware it runs significantly slower (half the speed on V8) of a simple "for" almost entirely because of the overhead of "from". The static Array.from basically is a "for" copy to a new array, so for all intents and purposes that's running the loop TWICE and doubling down on the memory footprint. To that end Array.from should be used with an eyedropper not a paint roller.

Write a reply...

Load more responses

Join a friendly and inclusive Q&A network for coders

  • 🖥Pick the technologies you like & read great content through your feed.
  • 💬Ask a question when you want to learn more about anything.
  • 🚀Share what you know & build your portfolio.
Sign up nowLearn more

loading ...