The only difference I see in map and foreach is that map
is returning an array and forEach
is not. However, I don\'t even understand the last line
TL;DR answer --
map always returns another array.
forEach does not. It is up to you to decide what it does. Return an array if you want or do something else if you don't.
Flexibility is desirable is certain situations. If it isn't for what you are dealing with then use map.
While all the previous questions are correct, I would definitely make a different distinction. The use of map
and forEach
can imply intent.
I like to use map
when I am simply transforming the existing data in some way (but want to make sure the original data is unchanged.
I like to use forEach
when I am modifying the collection in place.
For instance,
var b = [{ val: 1 }, { val: 2 }, { val: 3 }];
var c = b.map(function(el) {
return { val: el.val + 1 }; // modify element in-place
});
console.log(b);
// [{ val: 1 }, { val: 2 }, { val: 3 }]
console.log(c);
// [{ val: 3 }, { val: 4 }, { val: 5 }]
My rule of thumb being making sure when you map
you are always creating some new object/value to return for each element of the source list and returning it rather than just performing some operation on each element.
Unless you have any real need to modify the existing list, it doesn't really make sense to modify it in place, and fits better into functional/immutable programming styles.
The voted answer (from Ken Redler) is misleading.
A side effect in computer science means that a property of a function/method alters a global state [wiki]. In some narrow sense, this may also include reading from a global state, rather than from arguments. In imperative or OO programing, side effects appear most of the time. And you are probably making use of it without realizing.
The significiant difference between forEach
and map
is that map
allocates memory and stores the returning value, while forEach
throws it away. See emca spec for more information.
As for the reason why people say forEach
is used when you want a side effect is that the return value of forEach
is always undefined
. If it has no side effect (does not change global state), then the function is just wasting cpu time. An optimizing compiler will eliminate this code block and replace the it with the final value (undefined
).
By the way, it should be noted that JavaScript has no restriction on side effects. You can still modify the original array inside map
.
var a = [1,2,3]; //original
var b = a.map( function(x,i){a[i] = 2*x; return x+1} );
console.log("modified=%j\nnew array=%j",a,b);
// output:
// modified=[2,4,6]
// new array=[2,3,4]
Once again, I feel like a necromancer adding a response to a question that has been asked 5 years ago (happily there is rather recent activity, so I am not the only one disturbing the dead:).
Others have already posted about your main question regarding the difference between the functions. But for...
are there any real uses for these methods in javascript (since we aren't updating a database) other than to manipulate numbers like this:
...it's funny you should ask. Just today I wrote a piece of code that assigns a number of values from a regular expression to multiple variables using map for transformation. It was used to convert a very complicated text based structure into visualizeable data ... but for simplicity's sake, I shall offer an example using date strings, because those are probably more familiar for everyone (though, if my problem had actually been with dates, instead of map I would've used Date-object, which would've done the job splendidly on its own).
const DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/;
const TEST_STRING = '2016-01-04T03:20:00.000Z';
var [
iYear,
iMonth,
iDay,
iHour,
iMinute,
iSecond,
iMillisecond
] = DATE_REGEXP
// We take our regular expression and...
.exec(TEST_STRING)
// ...execute it against our string (resulting in an array of matches)...
.slice(1)
// ...drop the 0th element from those (which is the "full string match")...
.map(value => parseInt(value, 10));
// ...and map the rest of the values to integers...
// ...which we now have as individual variables at our perusal
console.debug('RESULT =>', iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond);
So ... while this was just an example - and only did a very basic transformation for the data (just for sake of example) ... having done this without map would've been a much more tedious task.
Granted, it is written in a version of JavaScript that I don't think too many browsers support yet (at least fully) but - we're getting there. If I needed to run it in browser, I believe it would transpile nicely.
The main difference between the two methods is conceptual and stylistic: You use forEach
when you want to do something to or with each element of an array (doing "with" is what the post you cite meant by "side-effects", I think), whereas you use map
when you want to copy and transform each element of an array (without changing the original).
Because both map
and forEach
call a function on each item in an array, and that function is user-defined, there is almost nothing you can do with one and not with the other. It's possible, though ugly, to use map
to modify an array in-place and/or do something with array elements:
var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.map(function(el) {
el.val++; // modify element in-place
alert(el.val); // do something with each element
});
// a now contains [{ val: 2 }, { val: 3 }, { val: 4 }]
but much cleaner and more obvious as to your intent to use forEach
:
var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.forEach(function(el) {
el.val++;
alert(el.val);
});
Especially if, as is usually the case in the real world, el
is a usefully human-readable variable:
cats.forEach(function(cat) {
cat.meow(); // nicer than cats[x].meow()
});
In the same way, you can easily use forEach
to make a new array:
var a = [1,2,3],
b = [];
a.forEach(function(el) {
b.push(el+1);
});
// b is now [2,3,4], a is unchanged
but it's cleaner to use map
:
var a = [1,2,3],
b = a.map(function(el) {
return el+1;
});
Note as well that, because map
makes a new array, it likely incurs at least some performance/memory hit when all you need is iteration, particularly for large arrays - see http://jsperf.com/map-foreach
As for why you'd want to use these functions, they're helpful any time you need to do array manipulation in javascript, which (even if we're just talking about javascript in a browser environment) is pretty often, almost any time you're accessing an array that you're not writing down by hand in your code. You might be dealing with an array of DOM elements on the page, or data pulled from an AJAX request, or data entered in a form by the user. One common example I run into is pulling data from an external API, where you might want to use map
to transform the data into the format you want and then use forEach
to iterate over your new array in order to display it to your user.
You can use map
as though it were forEach
.
It will do more than it has to, however.
scope
can be an arbitrary object; it's by no means necessarily this
.
As for whether there are real uses for map
and forEach
, as well to ask if there are real uses for for
or while
loops.