One of the core skill-sets a developer needs are some strategies to handling data. I don't know about you, but I feel like I'm always doing this type of work. Arrays are a super common structure we encounter a lot in JavaScript and ES6 brought along with it some pretty great new array methods. These new methods are really powerful and can substantially clean up your code. Let's take a look at map
today to get things started.
Basics
One of the most common operations we need to do is looping through a data-set and doing something to each item as you iterate through it. map
does just that. We're able to loop through an array and apply a callback function to each item of the array and return a brand new array in the end (this is an immutable array method).
Let's look at really basic example first. Let's say we've got a list of users' first names and last names and we'd like a list of all our users' full names.
const users = [
{
firstName: "Jerry",
lastName: "Garcia",
},
{
firstName: "Aretha",
lastName: "Franklin",
},
]
const usersFullNames = users.map(user => {
return `${user.firstName} ${user.lastName}`
})
console.log(usersFullNames) // ["Jerry Garcia", "Aretha Franklin"]
That'll give you the basic idea of how map
works. Also of note is that we have access to the index value as well. So if we wrote the above like this:
const usersFullNamesWithIndex = users.map((user, index) => {
return `${user.firstName} ${user.lastName} is ${index}`
})
console.log(usersFullNamesWithIndex) // ["Jerry Garcia is 0", "Aretha Franklin is 1"]
Notice the index value I've added to each name. I've not found that particularly useful all that often (which is why you often see it omitted from examples), but every once in a while it comes in handy so it's good to know that you have access to it should you need it.
Some Math
Another use for map
in a similar vein as the above example is performing some math operation on a data-set. Here's a stupidly simple example.
const someNumbers = [1, 4, 6, 2, 12]
const doubleThem = someNumbers.map(number => number*2)
console.log(doubleThem) // [2, 8, 12, 4, 24]
Pretty straightforward I'd say. We just spin through each number in our original array, double it and pass that value into our new array and before you know we we've got a fresh new set of double values (because hey...sometimes you just feel like doubling some numbers 😃).
With querySelectorAll
When we use a method like querySelectorAll we end up getting a NodeList of matching elements (which is essentially an array) as a return. So there's always an extra step necessary to get the data we're after. map
can clean this operation up quite a bit.
const posts = document.querySelectorAll(".posts")
posts.map(post => doSomething(post))
A pretty general example I realize, but you can see how map
can clean up your code a bit in this instance. Because NodeList is operable by array operations we can treat is as such and use our handy array methods. Is this much different than pulling out our trusty friend forEach()
? Probably not, but the point is, you can use map
in all sorts of different situations.
With Normalized Data
Let's explore a more interesting use-case. map
is a really handy tool for working with a normalized data-set. If this is a new concept for you it's certainly worth digging into a bit more, but we're not going to go into that right now.
Here's my ultra basic definition that'll serve our purposes here. Normalized data pushes a more flat structure and leverages ids to define relationships between data (check out the example below and I bet you'll start to see some of the patterns). There's more to it obviously, but the data structure below is a pretty common (albeit very simple) one you'll find these days. Essentially this structure provides us some great ways of looping through data and also methods of finding particular bits of data really quickly. It can look like more trouble than it's worth on the surface, but once you start to play around with it you'll see how great it is to work with.
Here's a super basic normalized data-set we'll use in some more examples below.
// Normalized data
const users = {
userIds: ["user-1", "user-2", "user-3"],
usersById: {
"user-1": { firstName: "Jerry", lastName: "Garcia" },
"user-2": { firstName: "Robert", lastName: "Plant" },
"user-3": { firstName: "Aretha", lastName: "Franklin" },
},
postIds: ["post-1", "post-2"],
postsById: {
"post-1": { title: "Post One Title", authorIds: ["user-1"] },
"post-2": { title: "Post Two Title", authorIds: ["user-1"] },
"post-3": { title: "Post Three Title", authorIds: ["user-2"] },
"post-4": { title: "Post Four Title", authorIds: ["user-1", "user-3"] },
}
}
Ok, let's do some work with this data. Let's grab a list of all our users.
const users = usersIds.map(id => usersById[id])
console.log(users)
// [
// {
// firstName: "Jerry",
// lastName: "Garcia"
// },
// {
// firstName: "Robert",
// lastName: "Plant"
// },
// {
// firstName: "Aretha",
// lastName: "Franklin"
// },
// ]
Cool, that's a nice iterable list of our users to work with.
And because we're using this normalized data structure we can still do cool stuff like pluck a single post out if we know the id. As opposed to looping over all posts searching for a matching id.
const singlePost = data.postsById["post-3"]
console.log(singlePost)
// { title: "Post Four Title", authorIds: ["user-1", "user-2"] }
Ok, that's nice. Now let's display the details of each user associated with the post we just grabbed. Time for map
again.
const singlePost = data.postsById["post-3"]
const singlePostAuthorIds = singlePost.authorIds
const singlePostAuthors = singlePostAuthorIds.map(id => data.usersById[id])
console.log(singlePostAuthors)
// [
// {
// firstName: "Jerry",
// lastName: "Garcia"
// },
// {
// firstName: "Aretha",
// lastName: "Franklin"
// },
// ]
Hey, cool. We've got another iterable list of users. This time just for this specific post.
I think it's pretty easy to see how powerful the combination of map
and normalized data can be even from our contrived little example.
The new array methods we got as part of ES6 are really powerful. map
is just one of them though probably the one you'll reach for most often. Even from our little messing around above I bet you can see all sorts of different use cases for such a method. I'm planning to do similar posts for some other fancy, new array methods coming up soon (filter
, reduce
). They're such great tools to add to your tool-belt. Stay tuned.
And as always I'll point you to the map over at MDN for some additional information for your learning pleasure.
Top comments (0)