Map & forEach
Open the project folder
In our starter files, open the index.html page from this lessons folder:
02.Arrays-In-More-Depth > 07.Map-forEach
The forEach
method
I want to now show you two more array methods called forEach
and map
. These two methods are also iteration methods, so they loop over each array value, and then run a callback function for each one.
Lots of the array methods we have covered so far are more specific, such as sorting an array, filtering, checking if one value exists, but forEach
and map
are more general use.
Their purpose or use is only limited to the code we write in the function. First let’s look at forEach
.
In the starter files, we have 2 arrays:
let numbers = [72, 33, 108, 222, 6];
let posts = [
{ title: 'How to learn Javascript', body: 'bla bla bla' },
{ title: 'How to be a ninja', body: 'bla bla bla' },
{ title: 'How to be a ninja part 2', body: 'bla bla bla' },
];
And we will begin by calling forEach
on the numbers array, using the shorter arrow function syntax:
numbers.forEach((number) => );
Just as a recap, if we can keep it all on one line, we can leave out the return keyword. If we want to use multiple lines, we add the curly braces and the return
keyword like this:
numbers.forEach((number) => {
//code
return
});
For this, we can do anything we want such as multiplying the numbers:
numbers.forEach((number) => console.log(number * 2));
The index number is also available if we add it in as a parameter:
numbers.forEach((number, index) =>
console.log(`number ${index}: ${number * 2}`)
);
All these indexes begin at zero, we can also change this to display from 1 onwards if we prefer, by adding +1 to the output:
numbers.forEach((number, index) =>
console.log(`number ${index + 1}: ${number * 2}`)
);
Any code can be wrote inside of this function, taking our posts array from above, let’s look at an example with an array of objects. This is going to take our posts title, and transform the text to uppercase:
posts.forEach((post) => console.log(post.title.toUpperCase() ) );
Just as we have been using lots of array methods in this section, toUpperCase
is also a method, but it is a string method, so we call it on a string of text such as our post title.
The map
method
This is forEach
and we also have something similar called map
:
posts.map((post) => console.log(post.title.toUpperCase()));
The console shows the same result as when using forEach
, so what is the difference?
Differences between map
and forEach
There are a couple of reasons they differ, and one is the return value. To see this, first remove the console log wrapper, leaving this:
posts.map((post) => post.title.toUpperCase());
We then need to store the return value into a variable, and change back to use forEach
:
const newPosts = posts.forEach((post) => post.title.toUpperCase());
console.log(newPosts); // undefined
We get back undefined
because nothing is returned. The forEach
method will run a function for each array value and modify the original array.
Map on the other hand, leaves the original array, and returns a new one with the modified values, which you can see by changing this to use map
:
const newPosts = posts.map((post) => post.title.toUpperCase());
console.log(newPosts); // ['HOW TO LEARN JAVASCRIPT', 'HOW TO BE A NINJA', 'HOW TO BE A NINJA PART 2']
This return value is one of the differences. Another difference is we can also chain multiple methods using map
.
Chaining methods
At the end of the map
method, we add a dot followed by the method we want to chain, such as filter()
:
const newPosts = posts
.map((post) => post.title.toUpperCase())
.filter((value) => value === 'HOW TO BE A NINJA PART 2');
console.log(newPosts);
This will return a new array with the found post. If we wanted to check if this title is included in the array, we could use the some()
method:
const newPosts = posts
.map((post) => post.title.toUpperCase())
.some((value) => value === 'HOW TO BE A NINJA PART 2');
console.log(newPosts); // true
This will return true rather than a new array. We can use all methods we have previously looked at, including findIndex
to find the index number of this value:
const newPosts = posts
.map((post) => post.title.toUpperCase())
.findIndex((value) => value === 'HOW TO BE A NINJA PART 2');
console.log(newPosts); // 2
You can see with these examples that although all these methods may look complex to begin, many of them are structured the same, but just return different values. None of this chaining is available if we change to use forEach
:
const newPosts = posts
.forEach((post) => post.title.toUpperCase())
.findIndex((value) => value === 'HOW TO BE A NINJA PART 2');
console.log(newPosts);
This chaining is not possible because forEach returns undefined, rather than a new value:
Uncaught TypeError: Cannot read properties of undefined (reading 'findIndex')
To recap, if we want to modify the existing array and do not need a new one returned, we use forEach
. We use map
if we want to leave the original array untouched and return a new array with the values, and it is also good for chaining too.