Some of the most loved functions in JavaScript might be map
and forEach
. They both started to exist since ECMAScript 5, ores5
in short.
In this post, I am going to talk about the main difference between each and show you some examples of their usages.
Basically, looping over an object in JavaScript counts on whether or not the object is an iterable
. Arrays are iterable by default.
map
and forEach
are included in the Array.prototype
, so we don’t need to think about iterable
. If you want to study further, I recommend you check out what an iterable
object is in JavaScript!
map()
and forEach()
?map
and forEach
are helper methods in array to loop over an array easily. We used to loop over an array, like below, without any helper functions.
var array = ['1', '2', '3'];
for (var i = 0; i < array.length; i += 1) {
console.log(Number(array[i]));
}
// 1
// 2
// 3
medium_looping_origin.js
The for
loop has been with us since the very beginning of the JavaScript era. It takes 3 expressions: the initial value, condition, and final expression.
This is a classic way of looping an array. Since ECMAScript 5, new functions have appeared to make us happier.
map
does exactly the same thing as what the for
loop does, except that map
creates a new array with the result of calling a provided function on every element in the calling array.
It takes two parameters: a callback function that will be invoked later when map
or forEach
is called, and the context variable called thisArg
that a callback function will use when it’s invoked.
const arr = ['1', '2', '3'];
// callback function takes 3 parameters
// the current value of an array as the first parameter
// the position of the current value in an array as the second parameter
// the original source array as the third parameter
const cb = (str, i, origin) => {
console.log(`${i}: ${Number(str)} / ${origin}`);
};
arr.map(cb);
// 0: 1 / 1,2,3
// 1: 2 / 1,2,3
// 2: 3 / 1,2,3
medium_map_basic.js
The callback function can be used as below.
arr.map((str) => { console.log(Number(str)); })
The result of map
is not equal to the original array.
const arr = [1];
const new_arr = arr.map(d => d);
arr === new_arr; // false
You can also pass the object to the map
as thisArg
.
const obj = { name: 'Jane' };
[1].map(function() {
// { name: 'Jane' }
console.dir(this);
}, obj);
[1].map(() => {
// window
console.dir(this);
}, obj);
medium_map_thisArg.js
The object obj
became the thisArg
for map
. But the arrow callback function can’t get obj
as its thisArg
.
This is because arrow functions work differently from normal functions. Visit this article to see what’s different between arrow functions and normal functions.
forEach
is another looping function for an array but there’s a difference between map
and forEach
in use. There are two parameters that map
and forEach
can take — a callback function and thisArg
which they use as their this.
const arr = ['1', '2', '3'];
// callback function takes 3 parameters
// the current value of an array as the first parameter
// the position of the current value in an array as the second parameter
// the original source array as the third parameter
const cb = (str, i, origin) => {
console.log(`${i}: ${Number(str)} / ${origin}`);
};
arr.forEach(cb);
// 0: 1 / 1,2,3
// 1: 2 / 1,2,3
// 2: 3 / 1,2,3
medium_forEach.js
Then, what’s different?
map
returns a new array of its original array. forEach
, however, does not. But both of them ensure the immutability of the original object.
[1,2,3].map(d => d + 1); // [2, 3, 4];
[1,2,3].forEach(d => d + 1); // undefined;
~~ Edit ~~
forEach
doesn’t ensure the immutability of an array if you change values inside an array. This method only ensures immutability when you don’t touch any values inside.
[{a: 1, b: 2}, {a: 10, b: 20}].forEach((obj) => obj.a += 1);
// [{a: 2, b: 2}, {a: 11, b: 21}]
// The array has been changed!
The example above is from Kenny Martin Rguez. Thank you! 👏
Since the main difference between them is whether or not there is a return value, you would want to use map
to make a new array and use forEach
just to map over the array.
This is a simple example.
const people = [
{ name: 'Josh', whatCanDo: 'painting' },
{ name: 'Lay', whatCanDo: 'security' },
{ name: 'Ralph', whatCanDo: 'cleaning' }
];
function makeWorkers(people) {
return people.map((person) => {
const { name, whatCanDo } = person;
return <li key={name}>My name is {name}, I can do {whatCanDo}</li>
});
}
<ul>makeWorkers(people)</ul>
medium_when_to_use_map.js
In React, for example, map
is used very commonly to make elements because map
creates and returns a new array after manipulating data of the original array.
const mySubjectId = ['154', '773', '245'];
function countSubjects(subjects) {
let cnt = 0;
subjects.forEach(subject => {
if (mySubjectId.includes(subject.id)) {
cnt += 1;
}
});
return cnt;
}
countSubjects([
{ id: '223', teacher: 'Mark' },
{ id: '154', teacher: 'Linda' }
]);
// 1
medium_when_to_use_forEach.js
On the other hand, forEach
is useful when you want to do something with the data without creating a new array. By the way, the example could be refactored using filter
.
subjects.filter(subject => mySubjectId.includes(subject.id)).length;
To summarize, I recommend you use map
when creating a new array that you will use, and use forEach
when you don’t need to make a new array, but rather, there’s something you want to do with the data.
Some posts mentioned map
is faster than forEach
. So, I was curious if it’s for real. I found this comparison result:
The code looks very similar but the results are the opposite. Some tests said forEach
is faster and some said map
is faster.
Maybe you are telling yourself that map
/forEach
is faster than the other, and you might be right. I’m not sure, honestly. I think readability is much more important than the speed between map
and forEach
when it comes to modern web development.
But one thing’s for sure — both of them are slower than the built-in feature of JavaScript, for
loop.
map
and forEach
are handy functions for looping over an iterable object and might beautify your code and give you more readability.
But one really important keynote to keep in mind is to understand what each does and when to use each.
map
would be good when you want to make a new array that does not affect the original array, and forEach
would be nicer when you just want to map over an array.
forEach
is fastermap
is faster#javascript #programming