279

I know that there were a lot of topics like this. And I know the basics: .forEach() operates on original array and .map() on the new one.

In my case:

function practice (i){
    return i+1;
};

var a = [ -1, 0, 1, 2, 3, 4, 5 ];
var b = [ 0 ];
var c = [ 0 ];
console.log(a);
b = a.forEach(practice);
console.log("=====");
console.log(a);
console.log(b);
c = a.map(practice);
console.log("=====");
console.log(a);
console.log(c);

And this is output:

[ -1, 0, 1, 2, 3, 4, 5 ]
=====
[ -1, 0, 1, 2, 3, 4, 5 ]
undefined
=====
[ -1, 0, 1, 2, 3, 4, 5 ]
[ 0, 1, 2, 3, 4, 5, 6 ]

I can't understand why using practice changes value of b to undefined.
I'm sorry if this is silly question, but I'm quite new in this language and answers I found so far didn't satisfy me.

8
  • 130
    It’s this simple: .map returns a new array, whereas .forEach doesn’t return anything. Basically, if you want to obtain a modified form of the previous array, you use .map, if you don’t want that, you use .forEach. Commented Dec 22, 2015 at 23:56
  • 3
    Possible duplicate of what use does the javascript forEach method have (that map can't do)? Commented Dec 23, 2015 at 0:00
  • 1
    @Xufox - I red this topic before creating new one, but answer didn't satisfiy me. Commented Dec 23, 2015 at 0:02
  • 1
    Don’t just say it didn’t satisfy you. How exactly doesn’t it answer your question (have you read all the answers?)? What is your specific question that isn’t covered by the proposed duplicate target? Commented Dec 23, 2015 at 0:04
  • 1
    @Xufox That question deals with self-implemented functions, and is not really about the standardized ES5 functions. Commented Dec 23, 2015 at 0:05

16 Answers 16

373

They are not one and the same. Let me explain the difference.

forEach: This iterates over a list and applies some operation with side effects to each list member (example: saving every list item to the database) and does not return anything.

map: This iterates over a list, transforms each member of that list, and returns another list of the same size with the transformed members (example: transforming list of strings to uppercase). It does not mutate the array on which it is called (although the callback function may do so).

References

Array.prototype.forEach() - JavaScript | MDN

Array.prototype.map() - JavaScript | MDN

Sign up to request clarification or add additional context in comments.

6 Comments

map return list and forEach not . OK
One extra thing to keep in mind if you encounter a codebase with .maps instead of .forEach's: IE <=10 does not support the .forEach, so a much used workaround is to use .map instead
Are you sure that forEach modifies the original array?
@johnywhy Where in the answer does it state that?
@johnywhy .forEach shouldn't be used to edit the original array. You can think of it as displaying something in your frontend (i.e. React), you can use .forEach to display some elements on the list, etc. .map is more functional, and the right way for it. To illustrate, as an example, it can be used for inserting multiple data into multiple rows maybe.
|
114
  • Array.forEach “executes a provided function once per array element.”

  • Array.map “creates a new array with the results of calling a provided function on every element in this array.”

So, forEach doesn’t actually return anything. It just calls the function for each array element and then it’s done. So whatever you return within that called function is simply discarded.

On the other hand, map will similarly call the function for each array element but instead of discarding its return value, it will capture it and build a new array of those return values.

This also means that you could use map wherever you are using forEach but you still shouldn’t do that so you don’t collect the return values without any purpose. It’s just more efficient to not collect them if you don’t need them.

7 Comments

Of note: in 2015, it would have been arguable that forEach would have "been more efficient" than map especially if a polyfill was required to support forEach on an older browser (IE8 or 9). You don't need to assign the return of map to anything; the return value should get garbage collected immediately after map returns when the return of map is not assigned.
@cowbert Just because something is garbage collected immediately, that does not mean that you are not getting hit by the allocations that were necessary. So forEach will conceptually still be more efficient and better suited for tasks where you do not need to collect results. And I don’t know about you but in 2015, I was not developing for IE8 anymore (which btw. also didn’t support map); and IE9+ support forEach. And actually a month after my answer, Microsoft ended support for those browsers.
Are both forEach and map guaranteed to process the elements in the same order?
@Quentin2 Yeah, also, both functions are synchronous, so map and forEach calls will only return once the whole array has been looped through and the callback has been called for each.
@johnywhy The better question is how does abusing map benefit you?
|
85
forEach() map()
Functionality Performs given operation on each element of the array Performs given "transformation" on a "copy" of each element
Return value Returns undefined Returns new array with transformed elements, leaving back original array unchanged.
Preferrable usage scenario and example Performing non-tranformation like processing on each element.

For example, saving all elements in the database.
Obtaining array containing output of some processing done on each element of the array.

For example, obtaining array of lengths of each string in the array

forEach() example

chars = ['Hello' , 'world!!!'] ;
    
var retVal = chars.forEach(function(word){
  console.log("Saving to db: " + word) 
})
  
console.log(retVal) //undefined

map() example

 chars = ['Hello' , 'world!!!'] ;
    
 var lengths = chars.map(function(word){
   return word.length
 }) 
    
 console.log(lengths) //[5,8]

Comments

26

The main difference that you need to know is .map() returns a new array while .forEach() doesn't. That is why you see that difference in the output. .forEach() just operates on every value in the array.

Read up:

You might also want to check out: - Array.prototype.every() - JavaScript | MDN

Comments

15

Performance Analysis For loops performs faster than map or foreach as number of elements in a array increases.

let array = [];
for (var i = 0; i < 20000000; i++) {
  array.push(i)
}

console.time('map');
array.map(num => {
  return num * 4;
});
console.timeEnd('map');


console.time('forEach');
array.forEach((num, index) => {
  return array[index] = num * 4;
});
console.timeEnd('forEach');

console.time('for');
for (i = 0; i < array.length; i++) {
  array[i] = array[i] * 2;

}
console.timeEnd('for');

4 Comments

Here is the result on my computer: map: 1642ms forEach: 885ms for: 748ms
This test is not very scientific. It'd need to test them all doing the same thing. map is building an array, foreach is editing an array in place, and the for loop is modifying the other array in place also. When I modify the tests to actually do the same thing, map is faster than foreach.
I would argue it is scientific when used for the case of "I need to do something to each array element, what should I use?" question. For a direct comparison of all the operations then you're right, but for people who come here asking if map is quicker than forEach for just looping, this is a valuable answer.
@Anther wins this debate. I came to this page wondering if i can use map in place of forEach without sacrificing performance. The answer, if Anther's results are accurate, is "yes".
12

forEach() :

  • return value : undefined

  • originalArray : not modified after the method call

  • newArray is not created after the end of method call.


map() :

  • return value : new Array populated with the results of calling a provided function on every element in the calling array

  • originalArray : not modified after the method call

  • newArray is created after the end of method call.


Conclusion:

Since map builds a new array, using it when you aren't using the returned array is an anti-pattern; use forEach or for-of instead.

1 Comment

Based on reading this page, it seems there's no downside to using .map for everything. It's fewer characters to type, loops at least as fast as .forEach, and then i can just remember one method.
11

map returns a new array.

forEach has no return value.

That's the heart of the difference. Most of the other answers here say effectively that, but in a much more convoluted way.

Comments

9

forEach: If you want to perform an action on the elements of an Array and it is same as you use for loop. The result of this method does not give us an output buy just loop through the elements.

map: If you want to perform an action on the elements of an array and also you want to store the output of your action into an Array. This is similar to for loop within a function that returns the result after each iteration.

Hope this helps.

Comments

6

The difference lies in what they return. After execution:

arr.map()

returns an array of elements resulting from the processed function; while:

arr.forEach()

returns undefined.

Comments

4

Difference between forEach() & map()

forEach() just loop through the elements. It's throws away return values and always returns undefined.The result of this method does not give us an output .

map() loop through the elements allocates memory and stores return values by iterating main array

Example:

   var numbers = [2,3,5,7];

   var forEachNum = numbers.forEach(function(number){
      return number
   })
   console.log(forEachNum)
   //output undefined

   var mapNum = numbers.map(function(number){
      return number
   })
   console.log(mapNum)
   //output [2,3,5,7]

map() is faster than forEach()

2 Comments

How do you know map is faster than forEach?
What tests did you do to come to that conclusion?
3

Diffrence between Foreach & map :

Map() : If you use map then map can return new array by iterating main array.

Foreach() : If you use Foreach then it can not return anything for each can iterating main array.

useFul link : use this link for understanding diffrence

https://codeburst.io/javascript-map-vs-foreach-f38111822c0f

Comments

3

.map and .forEach will do just about then same thing, until you start operating on arrays with millions of elements. .map will create another collection with the same size (and possibly type, depending on the array species) which could use up a LOT of memory. .forEach will not do this.

2 Comments

I specified that difference above.
@Asker this answer seems accurate to me.
3

One thing to point out is that both methods skips uninitialized values, but map keeps them in the returned array.

var arr = [1, , 3];

arr.forEach(function(element) {
    console.log(element);
});
//Expected output: 1 3

console.log(arr.map(element => element));
//Expected output: [1, undefined, 3];

1 Comment

In Node.js v14.15.0, the output of console.log(arr.map(element => element)); is [ 1, <1 empty item>, 3 ].
3

One of the subtle differences not mentioned here is that forEach() can loop over a static (not live) NodeList while map() cannot

Works perfectly:

document
    .querySelectorAll('.score')
    .forEach(element=>console.log(element));

Uncaught "TypeError: document.querySelectorAll(...).map is not a function":

document
    .querySelectorAll('.score')
    .map(element=>console.log(element));

19 Comments

The NodeList returned by querySelectorAll() is not an array. It happens to forEach(). That imply that 1. a NodeList has to implement a .map() methid. It is perfectly fine it it doesn't. 2. It doesn't imply that map() cannot loop over a NodeList - the .map() method is generic and applicable to any array-like, so Array.prototype.map.call( document.querySelectorAll(".score"), element=>console.log(element) ) would work.
@VLAZ Your comment is unclear. Can .map iterate over nodes or not? Is the code in this answer wrong?
@johnywhy "Can .map iterate over nodes or not?" yes, it can. I've demonstrated how. "Is the code in this answer wrong?" the code - no. Well, except document.querySelectorAll('.score').map(element=>console.log(element)); but it does mention it throws an error. The text is wrong. NodeList and arrays both have a .forEach(). Trying to call a method with the same name on two different objects, doesn't imply which object the method can operate on. So, the error is not related to .map() itself but because to NodeList. And array's .map() can be applied to NodeLists.
@VLAZ Thx! So you agree that map can be used instead of forEach in all cases?
@johnywhy no, I don't. Only use it when you do mapping. Don't use it when you don't do mapping. Use a loop or .forEach for those.
|
1

Performance Analysis (again - not very scientific)
In my experience sometime .map() can be faster than .foreach()

let rows = [];

    for (let i = 0; i < 10000000; i++) {
      // console.log("here", i)
      rows.push({ id: i, title: 'ciao' });
    }

    const now1 = Date.now();

    rows.forEach(row => {
      if (!row.event_title) {
        row.event_title = `no title ${row.event_type}`;
      }
    });

    const now2 = Date.now();

    rows = rows.map(row => {
      if (!row.event_title) {
        row.event_title = `no title ${row.event_type}`;
      }
      return row;
    });

    const now3 = Date.now();

    const time1 = now2 - now1;
    const time2 = now3 - now2;
    console.log('forEach time', time1);
    console.log('.map time', time2);

On my macbook pro (late 2013)

  • forEach time 1909
  • .map time 444

2 Comments

It's great to have these stats! At the moment, based on what i've read here, it seems i can just use .map in place of .forEach as standard practice. One question is: can map and forEach both iterate over nodes?
This is very flawed because the rows are modified in forEach, but not modified in the map. You can tell because if you switch the forEach and the map, you'll note the second one is always faster. However, the speed difference of map() vs forEach() is certainly negligible and you should use whichever one makes the most sense when reading.
-4

Map implicitly returns while forEach does not.

This is why when you're coding a JSX application, you almost always use map instead of forEach to display content in React.

1 Comment

No, this is completely wrong as of this writing. map does not "implicitly return", whatever that means. Instead, it explicitly returns a new array.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.