How The Hell Do I Use Map?

I often encourage my students to use the array functions map, reduce, and filter but they rarely feel comfortable with them, which is really a shame because they are like a swiss army knife with a mounted flashlight. These three functions could probably remove thousands of lines of your most confusing buggy code. Let us start with the all-star of the bunch map.

Map is an interesting type of function, it can look extremely strange at first like someone has peeled away the JavaScript you know and love to expose some ancient alien technology.

array.map(x => x * 5) // What r u even Doing tho!!!!

Let's break down this line of code just to achieve a baseline.

First I would like to point out the arrow function x => x * 5 (if you are unfamiliar with what arrow functions are read this Blog Post! where I hopefully explain them pretty well.)

What is a function doing there? Is this a callback? Well... sort of... but no. It kind of helps to think of it as a call back if you want, in that it is a function passed and an argument, and another function determines its execution... So in a few ways, it is like a callback. Still, it is not a callback, instead, it is referred to as a Higher Order Function which is a blog post for another day.

Ok, ok, so map takes a function as an argument... But why? What does it do with it?

Well, map just iterates over your array, meaning it takes each item of the array one by one and passes it into the function you supplied.

So if you were to see this

const scores = [90, 80, 25, 50]

const doubleScores = sores.map(x => x * 2)

Then you could determine that doubleScores will be calculated by taking each item in scores and running it through x => x * 2. So what will that leave us with?

Well, it has to be an array too right, because we need to store 4 results. So we know doubleScores is going to be an array. And it is an array filled with the results of doubling some other arrays contents.

// A way to visualize what map is doing
cosnt scores = [90, 80, 25, 50]
const double = x => x * 2
const doubleScores = [ double(scores[0]),
                       double(scores[1]),
                       double(scores[2]),
                       double(scores[3]) ]

Ok, so then what does map do?

Well, one way to explain it is that it allows you to take a function that expects single items as arguments, like in the above case, a single number. And use this function with an array of many items. Whoa... it's like a pocket for loop that every array is just carrying around with it.

This is actually pretty dope because that means instead of writing for loops, I can write simple functions that are used to operating on single items and just presto-chango use them to transform lists of items. This is really great because for loops have cruft and boilerplate that can mask what the actual intention of the code is. Consider the following code.

const students = [
  { name: 'Leroy Jenkins', grade: 55 },
  { name: 'Tommy Pickles', grade: 98 },
  { name: 'Mike Tyson', grade: 85 },
  { name: 'Donnie Darko', grade: 90 },
]

// A simple function expecting a single student,
//  and returns true if they pass the class and fail otherwise.
const isPassing = student => student.grade >= 65

// Usage with a single student
const tommyPickles = students[1]
const didTommyPass = isPassing(tommyPickles)

// Usage with the entire list
const classResults = students.map(isPassing)

// Extra credit c-c-combo usage with filter
const onlyWinners = students.filter(isPassing) // more on this next week.

How slick is that? Can you imagine trying to use that function in the middle of a for loop? It would look like a mess, instead, it looks like a beautiful one line declaration. Map gives us superpowers! And when I say its like a pocket for loop I mean it, literally any for loop can be re-written using map, and it usually turns out much simpler. For example, the above first written as a for loop looks like this

const scores = [90, 80, 25, 50]
const doubleScores = []
for (var i = 0; i < scores.length; i++) {
  doubleScores.push(scores[i] * 2)
}

Eww wtf no. Bring back the map version
const doubleScores = scores.map(x => x * 2)
ohhhh yes... much better.

See the difference? The map version fits on one line, has much less cruft, and makes you look so much cooler... ok maybe that last part is not true. The larger point is true though, there is rarely a need to write for loops if you know your way around map. I actually have not written a for loop in so long that I had to double check MDN when writing the one you see above. I honestly just don't use them much anymore.

Join My Newsletter!

Get notified every time a new post goes live, and recieve juicy goodies right in your inbox.