239

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.

GG.
  • 21,083
  • 14
  • 84
  • 130
DzikiChrzan
  • 2,747
  • 2
  • 15
  • 22
  • 112
    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`. – Sebastian Simon Dec 22 '15 at 23:56
  • 2
    Possible duplicate of [what use does the javascript forEach method have (that map can't do)?](http://stackoverflow.com/questions/3034392/what-use-does-the-javascript-foreach-method-have-that-map-cant-do) – Sebastian Simon Dec 23 '15 at 00:00
  • 1
    @Xufox - I red this topic before creating new one, but answer didn't satisfiy me. – DzikiChrzan Dec 23 '15 at 00: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? – Sebastian Simon Dec 23 '15 at 00:04
  • 1
    @Xufox That question deals with self-implemented functions, and is not really about the standardized ES5 functions. – poke Dec 23 '15 at 00:05
  • See the article [JavaScript — Map vs. ForEach](https://codeburst.io/javascript-map-vs-foreach-f38111822c0f) – Michael Freidgeim May 17 '19 at 23:18
  • See also the language-agnostic [Is there a difference between foreach and map?](https://stackoverflow.com/q/354909/1048572) – Bergi Aug 19 '20 at 20:51
  • I'm not sure it's correct to say that forEach operates on the original array. I believe neither modifies the original array. – johny why Nov 17 '22 at 15:46

16 Answers16

328

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

FZs
  • 16,581
  • 13
  • 41
  • 50
Richard Hamilton
  • 25,478
  • 10
  • 60
  • 87
104
  • 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.

poke
  • 369,085
  • 72
  • 557
  • 602
  • 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 Mar 23 '18 at 00:40
  • 4
    @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. – poke Mar 23 '18 at 08:54
  • Are both forEach and map guaranteed to process the elements in the same order? – Quentin 2 Jul 20 '18 at 15:18
  • 1
    @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. – poke Jul 21 '18 at 10:17
  • If you use `map` in place of `forEach`, you're not "collecting" anything. So what's the harm? – johny why Nov 17 '22 at 15:49
  • @poke "forEach will conceptually still be more efficient" -- Does anyone have any statistics to support that? – johny why Nov 17 '22 at 15:50
  • @johnywhy The better question is how does abusing `map` benefit you? – Unmitigated Apr 30 '23 at 19:30
78
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]
Mahesha999
  • 22,693
  • 29
  • 116
  • 189
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

Rahul Desai
  • 15,242
  • 19
  • 83
  • 138
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');
Community
  • 1
  • 1
sonia kaushal
  • 495
  • 6
  • 5
  • 3
    Here is the result on my computer: `map: 1642ms forEach: 885ms for: 748ms` – Flavio Vilante Mar 15 '20 at 21:36
  • 1
    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. – Anther Jul 22 '21 at 22:14
  • 3
    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. – Deef Aug 10 '21 at 07:56
  • @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". – johny why Nov 17 '22 at 15:53
10

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.

Asker
  • 1,299
  • 2
  • 14
  • 31
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.

9

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.

Vega
  • 27,856
  • 27
  • 95
  • 103
Harsha Vardhan Chakka
  • 1,357
  • 1
  • 9
  • 7
  • 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. – johny why Nov 17 '22 at 15:57
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.

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Godwin Ekuma
  • 81
  • 1
  • 6
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()

Razib Hossain
  • 708
  • 5
  • 13
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];
Conny Olsson
  • 1,567
  • 2
  • 11
  • 19
  • In Node.js v14.15.0, the output of `console.log(arr.map(element => element));` is `[ 1, <1 empty item>, 3 ]`. – VCD Apr 22 '21 at 01:09
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

Prakash Harvani
  • 1,007
  • 7
  • 18
3

one of the shuttle difference not mentioned here is that forEach() can loop over 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));
Prakhar Gyawali
  • 527
  • 4
  • 18
  • 1
    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 Dec 10 '21 at 21:59
  • @VLAZ Your comment is unclear. Can `.map` iterate over nodes or not? Is the code in this answer wrong? – johny why Nov 17 '22 at 15:59
  • 1
    @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 Nov 17 '22 at 16:08
  • @VLAZ Thx! So you agree that `map` can be used instead of `forEach` in all cases? – johny why Nov 17 '22 at 16:11
  • @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. – VLAZ Nov 17 '22 at 16:12
  • @VLAZ Why? What's the impact on code, readability, performance, etc? – johny why Nov 17 '22 at 16:13
  • @johnywhy [Is performing a mapping operation without using returned value an antipattern?](https://stackoverflow.com/q/56903693). Performance is indeed one aspect. But readability is a very big other aspect. Overall, you can use a hammer to spread butter on your sandwich but the performance and maintainability of that sandwitch would not be the same as if you used a knife. – VLAZ Nov 17 '22 at 16:15
  • @VLAZ According to tests performed by a few people on this page, `map` will perform at least as fast as `forEach`, or faster. So if performance is the question, `map` is equal to or better than `forEach`. What do you mean about "maintainability"? – johny why Nov 17 '22 at 16:26
  • @johnywhy the tests probably don't account for GC runs afterwards. As for maintainability - do you reckon it's completely reasonable and expected `person.getName()` will *delete* the person? Because I personally don't. And for the very same reason, I don't think `arr.map()` is maintainable if it doesn't do mapping. Breaks expectations, misuses idioms, it's hard to reason about and potentially refactor, without being thoroughly familiar with details that are supposed to be abstracted away. – VLAZ Nov 17 '22 at 16:31
  • @VLAZ `person.getName()` will delete the person? – johny why Nov 17 '22 at 16:33
  • @johnywhy example analogous to using `.map()` for operations that aren't mapping. Normally, the expectation is that `getX` will not change anything and just give you `X`. Similar to how `.map()` sets up the expectation that a transformation is being made and it would give you the transformed values. You seem surprised indicating that your expectation for `person.getName()` is subverted. Same thing happens when `.map()` is misused. Subverted expectations. As I said, it makes the code harder to reason about. – VLAZ Nov 17 '22 at 16:40
  • @VLAZ Bad comparison. `map` doesn't delete, modify, or damage anything. You could also create a new array using forEach instead of map, and it would be valid code. map just makes it a bit easier. – johny why Nov 17 '22 at 16:41
  • @johnywhy no, it's a very apt comparison. It's not *supposed to*. The same way `getName()` also not *supposed to*. You yourself suggested that it's interchangeable with `.forEach()` which then means that mutation is to be tolerated, yet it goes counter to what mapping is. I really don't think this is getting anywhere as you seem to be trying to deliberately ignore what I'm saying. So, here is hopefully the last thing to say: If you tolerate code like `arr.map(x => { arr.shift() })` that's on you, just know you're wrong for doing so. – VLAZ Nov 17 '22 at 16:45
  • i'm listening very carefully to what you're saying, and you seem to be making a false statement. You're asserting that if `map` is used instead of `forEach`, the array will definitely get mutated. That seems obviously false. Neither function, map or forEach mutate the original array. Before `map` or `forEach` existed there wasn't any loop statement which returned an array. – johny why Nov 17 '22 at 21:52
  • `forEach` could be used to mutate the original array, same as `map`. No difference. – johny why Nov 17 '22 at 21:59
  • @johnywhy No, I'm not saying that using `.map()` will mutate the array. I said it shouldn't be used *when not doing a mapping operation*. You disagreed with that. Thus you are saying that `.map()` should be used for non-idiomatic purpose. The entire point with `getName()` is that - using a non-idiomatic code hurts the clarity. – VLAZ Nov 18 '22 at 07:02
  • "*forEach could be used to mutate the original array, same as map. No difference*" the ***only*** valid `.forEach()` call is one that has side-effects. This is quite different to the idiomatic `.map()` call which doesn't. Just how `getName()` would idiomatically not have side-effects. – VLAZ Nov 18 '22 at 07:02
  • Aside from map and forEach, there are myriad functions one can create, some which return something, some which don't, some which have side-effects, some which don't, with no clues given to someone reading the code (like "oh, they're using map, so this is supposed to return an array"). In myriad cases, there are no available clues as to whether or not a function returns something other than *reading the code and comments*. So it seems a bit absurd to be so strict about this one limited case (map vs forEach) when so much other code doesn't offer such signposts. – johny why Nov 18 '22 at 08:41
  • @VLAZ I'm playing devil's advocate here, but sincere. Using map instead of forEach appeals because that simplifies my coding effort. You're insisting to use a less performant, less capable iterator, simply for self-documentation. But self-documentation is about meaningful variable names and function names supported by rich commenting, which I already do. In some languages, there's only ONE iterator -- people manage. https://www.sitepoint.com/self-documenting-javascript/ – johny why Nov 18 '22 at 18:53
1

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

Sean Morris
  • 384
  • 2
  • 9
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
Gas
  • 420
  • 1
  • 5
  • 10
  • 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? – johny why Nov 17 '22 at 16:02
-2

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.

  • No, this is completely wrong as of this writing. `map` does not "implicitly return", whatever that means. Instead, it explicitly returns a new array. – Asker Apr 19 '21 at 09:55