fullstackpilot Logo
JavaScript map js map javascript map

JavaScript map - How to map over the array in JavaScript properly?

Martin Milo
By on

JavaScript map is another one of the essential methods you can use to loop through the array. The output of this method is a new array. If you don't need the output, you may rather use forEach method.

Table of Contents

JavaScript map - how to use it

Let's have a look at how to use the map array method with some examples.

The map method accepts a callback function, and optionally, we can pass thisArg (which will be used as this when executing the callback). The callback or provided function is called once on each item in an array in ascending order.

Anonymous function

const avengers = ['Thor', 'Iron man', 'Hulk']
// We passed an anonymous function as a callback to map
const out = avengers.map(function (avenger) {
return `${avenger} is cool!`
})
console.log(out)
// -- 👇 console.log output --
// Array(3) ["Thor is cool!", "Iron man is cool!", "Hulk is cool!"]

You can also rewrite the anonymous function if you want to use the ES6 arrow syntax. This would make it a one-liner:

const out = avengers.map((avenger) => `${avenger} is cool!`)

Callback as non-anonymous function

Although not as common, we can declare the callback as non-anonymous function. It's useful if the callback needs to be reused in our code.

const avengers = ['Thor', 'Iron man', 'Hulk']
// This function probably won't be needed anywhere else
// but let's pretend it would be
function displayInLog(avenger) {
return `${avenger} is cool!`
}
const out = avengers.map(displayInLog)
// ☝️ is shorthand of:
// avengers.map((avenger) => displayInLog(avenger))

JavaScript executes the callback once for every item in the array. There is no difference if we use callback (named function) or anonymous function. In the last example, iterated item (in our case avenger) is passed as a first parameter to the callback implicitly.

Map with index

Callback or anonymous function we pass to map has two more optional parameters. First of the optional parameters is the index.

const avengers = ['Thor', 'Iron man', 'Hulk']
const out = avengers.map(function (avenger, index) {
return `${index + 1}. avenger is ${avenger}`
})
console.log(out)
// -- 👇 console.log output --
/* Array(3) [
"1. avenger is Thor",
"2. avenger is Iron man",
"3. avenger is Hulk"
]
*/

Map with array (self)

Second optional parameter we can pass to the map's callback is the array itself. Why would you need to access the array if you already have the array to map over? You usually won't. Though there is one good example in which you might want to.

Let's pretend that we don't know what the array contains, nor we know it's length.

// We pretend that the data comes from the API
// and we don't know it's length
const avengers = ['Thor', 'Iron man', 'Hulk']
// Now let's pretend that we need to filter the data
// before we map over it
const out = avengers
.filter((avenger) => avenger !== 'Thor')
.map((avenger) => {
// Eh, so what's the array's length now?
})

We can console.log each avenger in the map though many devs just assign variable to the filtered array just for the sake of logging the length. This is quite often the case.

const filtered = avengers.filter((avenger) => avenger !== 'Thor')
console.log(filtered.length)
// -- 👇 console.log output --
// 2

If the code fails at certain point in this chain, I tend to look at how array looks like in specific step. But rewriting the code, and assigning variable just to do that is just annoying, and too much work. Let's do it differently.

Second optional callback param (self) to the rescue.

const out = avengers
.filter(avenger => avenger !== 'Thor')
.map((avenger, index, self) => {
return `${avenger} is one of ${self.length} other avengers`
})
// -- 👇 console.log output --
/* Array(2) [
"Iron man is one of 2 other avengers",
"Hulk is one of 2 other avengers",
]
*/

We don't need to assign new variable after filtering the data and then using a map even if we need to know the length. Pretty cool, isn't it?

Map over array-like objects

Array-like object are topics on their own, so let's just jump on the examples. If you're working in a browser environment with JavaScript, the most common array-like object you probably encounter is a NodeList - you can get it by trying document.querySelectorAll('p'). You may choose to get different element, not necessarily a paragraph.

You can't use map on NodeList as it would throw Uncaught TypeError: map is not a function. We need to first convert/copy the array-like object to the array. In the following example, we can see an array-like object:

const avengersInArrayLikeObject = {
"0": "Thor",
"1": "Iron man",
"2": "Hulk",
"length": 3
}

Now in order to map over the avengersInArrayLikeObject, we can't call map directly. It would throw the same error as with NodeList. We have couple of options though:

// Array-like object on which we can't use (call) map
// It would throw 'map is not a function' TypeError
const avengersInArrayLikeObject = {
"0": "Thor",
"1": "Iron man",
"2": "Hulk",
"length": 3
}
// Named function (callback) called 'fn'
function fn(avenger) {
return `${avenger} is just awesome!`
}
// Create new shallow copy from an array-like object
// Array.from returns an Array instance
const out1 = Array.from(avengersInArrayLikeObject).map(fn)
// We can call slice method
const out2 = Array.prototype.slice
.call(avengersInArrayLikeObject).map(fn)
// We can call map indirectly by using a call method
const out3 = Array.prototype.map
.call(avengersInArrayLikeObject, fn)

Conclusion

The map array method is extremely useful to rebuild the array and adjust each or specific item within the array.

You can also put side-effects in the callback you pass to map but keep in mind that under normal circumstances you can't break the iteration.

There are also several other useful array methods defined by ES5, such as:

I'll link these as soon as I cover them in the separate article. Consider reading up on them, as if you don't you may end up reinventing a method that already exists. For instance some and every are not as well-known as the other array methods.

Did you find the usage of map easy? Feel free to share a comment down below.

Share: