Write more readable code in JavaScript using the map array method
There are lots of array methods in JavaScript. map helps you to write non-mutating readable code in JavaScript.
The array is one of the most common data types in JavaScript. There are many useful methods associated with arrays like map
, filter
, reduce
, find
, some
, forEach
, push
, pop
, etc. In this article, I am gonna talk about map
method.
map
is a non-mutating method. So, if you do things right, the main array elements will not be affected (modified).
Map
map
method creates a new array with the same length from the original array. It is very helpful when you need to create a new array from the original array and you also want to do some operations on each item in the array.
map
structure:
const resultingArray = oldArray.map((currentValue, index, oldArr) => {
// return an element
}, this);
map
expects two parameters.
callback
function. This does the main job. We can use traditional function. OrES6
arrow
function. In our case,(currentValue, index, oldArr) => { // return an element }
this is thecallback
function.this
argument. You can use it asthis
value in thecallback
function. It is optional and rarely used.
Now, callback
function has 3 arguments.
currentValue
. This is the element or value being processed in every loop iteration.index
. This is optional. This represents the index ofcurrentValue
.array
. This is also an optional and rarely used argument. This represents the original array on whichmap
method was applied.
After processing, map
returns the resultingArray
without modifying oldArray
.
Example:
const persons = [
{ name: "Jane", age: 19 },
{ name: "John", age: 21 },
{ name: "Rick", age: 17 },
{ name: "David", age: 22 },
];
const names = persons.map((person) => person.name);
/*
* ES5 function syntax:
* const names = persons.map(function (person) {
* return person.name;
* });
*/
console.log(names);
// output: ['Jane', 'John', 'Rick', 'David']
In this example, we have created a new array containing only names. In the map
function, I am passing a function which takes a person and returns that person's name. So, it loops through the array, for every element in that array, it returns only the name
property hence creates a new array with only names.
If we wanted an array containing name and a flag to determine if the person is 20 plus aged, then we could do the following:
const persons = [
{ name: "Jane", age: 19 },
{ name: "John", age: 21 },
{ name: "Rick", age: 17 },
{ name: "David", age: 22 },
];
const newPersons = persons.map((person) => {
return { name: person.name, twentyPlus: person.age > 20 };
});
/*
* ES5 function syntax:
* const newPersons = persons.map(function (person) {
* return { name: person.name, twentyPlus: person.age > 20 };
* });
*/
console.log(newPersons);
/* output:
* [
* { name: 'Jane', twentyPlus: false },
* { name: 'John', twentyPlus: true },
* { name: 'Rick', twentyPlus: false },
* { name: 'David', twentyPlus: true }
* ]
*/
In this example, we have created a new array containing names and a flag to determine if the person's age is more than twenty or not. In the map
function, I am passing a function which takes a person and returns a new object. That object contains the person's name and a flag to determine if the person's age is more than twenty or not. So, it loops through the array, for every element in that array, it returns the name
property and that boolean value wrapped in an object hence creates a new array with names and twentyPlus
flag.
Now in the first example, I used shorthand syntax to return name and in the second example, I returned the new object explicitly.
We can use normal callback
function instead of ES6
arrow
function. But, arrow functions are more readable.
I will now share another example with index
and array
in callback
function:
const persons = [
{ name: "Jane", age: 19 },
{ name: "John", age: 21 },
{ name: "Rick", age: 17 },
{ name: "David", age: 22 },
];
// index will add 0, 1, 2, 3 respectively and array.length will
// add 4 for every new item's modifiedAge property
const newPersons = persons.map((person, index, array) => {
return { name: person.name, modifiedAge: person.age + index + array.length };
});
// ES5 function syntax:
// const newPersons = persons.map(function (person, index, array) {
// return { name: person.name, modifiedAge: person.age + index + array.length };
// });
console.log(newPersons);
// Output:
// [
// { name: 'Jane', modifiedAge: 23 },
// { name: 'John', modifiedAge: 26 },
// { name: 'Rick', modifiedAge: 23 },
// { name: 'David', modifiedAge: 29 }
// ]
All modern browsers support map
. You can find complere reference here
When not to use map
map
is not for every situations. When you do not want or need to return value or create new array with the same length, map should not be used. forEach or other array methods should be more suitable on those situations.
Why map is more readable
Suppose, you are creating a new array of persons with name and twentyPlus boolean flag like our second example with traditional for
loop. Then, the code should be like this:
let newPersons = [];
for (let i = 0; i < persons.length; i++) {
let person = {
name: persons[i].name,
twentyPlus: persons[i].age > 20,
};
newPersons.push(person);
}
You have to go through the whole code to understand that I am creating a new array. And the main logic of creating that array resides inside person
object creation part inside the for
loop. You will also have to check if I have written a break
or continue
statement to skip any particular value or not.
On the other hand, as soon as you see a map
method, you know that I am creating a new array of the same length. As new array must be of the same length, I cannot use break
or continue
to skip values.
const newPersons = persons.map((person) => {
return { name: person.name, twentyPlus: person.age > 20 };
});
When we use map
, we can focus more on logic cause it's purpose is defined.
Conclusion
map
is a very handy array method. It has a specific purpose. That purpose is: creating a new (modified) array with the same length. Whenever we need this functionality in our code, we should be using map
for better readability and maintainability.