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.