Sometimes i see some linter errors when using map which is resolved if i convert it to forEach. Anyone care to explain :D

Write your answer…

8 answers

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);
    });
Clap2
Spot On2
Show all replies

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 :)

Reply to this…

Hashnode is building a friendly and inclusive dev community. Come jump on the bandwagon!

  • 💬 A beginner friendly place

  • 🧠 Stay in the loop and grow your knowledge

  • 🍕 >500K developers share programming wisdom here

  • ❤️ Support the growing dev community!

Register ( 500k+ developers strong 👊)

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.

Clap1

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..

Show all replies

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.

Reply to this…

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

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.

Load more responses