0

Here's something I don't understand. The map function, which I just learned about a few days ago, is supposed to be some amazing function that will transform the way I write code if I find uses for it. But I still don't see how it's any different than forEach. The only difference is that the function passed to map replaces the current element with the return value. But forEach can do that too, which means that map is just a less general version of forEach.

Example on MDN:

var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots is now [1, 2, 3], numbers is still [1, 4, 9]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Ok, cool, I guess?

I can do that with forEach:

var numbers = [1, 4, 9];
var roots = numbers.forEach(function(el){el=Math.sqrt(el);});
// roots is now [1, 2, 3], numbers is still [1, 4, 9]

Other example:

var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.map(function(obj){ 
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});
// reformattedArray is now [{1:10}, {2:20}, {3:30}], 
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]

I can do that with forEach and it looks almost identical.

What's so good about map? What is an example where it works super-well where forEach wouldn't work?

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
Subpar Web Dev
  • 3,210
  • 7
  • 21
  • 35
  • forEach returns undefined and map does not. You can ask the same about `indexOf`. Just use forEach and remember the first index. Its just more convenient. – Cromon Apr 15 '16 at 22:35
  • You shlould search first: http://stackoverflow.com/questions/354909/is-there-a-difference-between-foreach-and-map http://stackoverflow.com/questions/3034392/what-use-does-the-javascript-foreach-method-have-that-map-cant-do http://stackoverflow.com/questions/26815829/array-foreach-call-vs-array-map-call – Mottor Apr 15 '16 at 22:35
  • 3
    `roots` does not have the result you describe. https://jsfiddle.net/o77z9ch1/ –  Apr 15 '16 at 22:39
  • @nils Type-o. Fixed now. – Subpar Web Dev Apr 15 '16 at 22:39
  • Your `.forEach` example is wrong. – Barmar Apr 15 '16 at 23:07
  • forEach can't be clean and simple inline like `"1,2,3,4.5".split(",").map(Number)` – dandavis Apr 15 '16 at 23:09
  • No, you _can't_ do that with forEach (not like that, anyway). Try your first snippet in, say, chrome console. – Sergio Tulentsev Apr 18 '16 at 11:46

3 Answers3

8

The difference is that forEach "iterates over an array" and map "iterates over an array and returns the result"

var numbers = [1, 4, 9];

var roots = numbers.forEach(Math.sqrt);
// roots is undefined, numbers is still [1, 4, 9]

var roots = numbers.map(Math.sqrt);
// roots is [1, 2, 3], numbers is still [1, 4, 9]

What's so good about map? It keeps your code small and smart because you don't need to define anonymous functions for built-in functions.

var numbers = [1, 4, 9];

var roots = [];
numbers.forEach(function(val){ roots.push( Math.sqrt(val) ); });
// roots is now [1, 2, 3], numbers is still [1, 4, 9]

The value of returning the result (no pun intended) is proven in your existing example...

var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.map(function(obj){ // <---------------- map
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});
// reformattedArray is now [{1:10}, {2:20}, {3:30}], 
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]

var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.forEach(function(obj){ // <---------------- forEach
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});
// reformattedArray is now undefined, 
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
vahanpwns
  • 939
  • 5
  • 12
3

map

map iterates over a list and returns a new list, without changing anything else. It doesn't change the original list. It has no side effects. With map you can take a normal function that works with primitives and lift this function, so that it can work with lists of these primitives:

const map = (f, xs) => xs.map(x => f(x));
const sqr = x => x * x;

let xs = [1,2,3];
let x = 3;

sqr(x); // 9
sqr(xs); // Error
let ys = map(sqr, xs); // [1,4,9]
xs; // [1,2,3]

The example illustrates how map lifts sqr in the context of xs, so that it can square the elements of xs. In this way you can reuse normal functions for arrays.

forEach

forEach has no result value. A function without any result value is useless, unless it has some side effects. Hence forEach have to apply side effects to the elements it is iterating over, in order to do something meaningful:

let ys = xs.forEach(sqr); // undefined
xs; // [1,2,3]
// without side effects, nothing has happened

const sqrWithSideEffect = (x, idx, arr) => arr[idx] = x * x; // ugly, isn't it?
xs.forEach(sqrWithSideEffect); // 
xs; // [1,4,9]; // side effect: destructive update of xs

Conclusion: forEach comes from imperative, map from functional programming. Both represent opposing paradigms. So if you really want to understand the consequences of the differences between the two functions, you have to understand the differences between the two programming paradigms.

0

forEach vs. Map High Order Array Methods

const arr = [1,2,3]
const arr2 = [...arr,4,5]//see spread operator grepper answer for [...arr]
//the forEach doesn't return anything, it just loops through the array
arr2.forEach(function(item) {
  console.log(item + ' of ' + arr2.length)
})
//map allows us to return an array and store it into a new array
const arr3 = arr2.map(function(item) {
  //after performing some operation on all the objects of the array
  //we can then return all those values into a new array
  return item * 2
})

console.log(arr3)

Chack it

BiswajitPaloi
  • 586
  • 4
  • 16