Iterator Drill: Map
Learning Goals
- Define how the
map()
method works - Demonstrate
map()
withArray
s - Demonstrate
map()
with complex data structures - Use
map()
to generate a new array
Introduction
As developers, we find ourselves responsible for all sorts of common, but
tedious, tasks, such as iterating over arrays. Although a for
loop or nesting
in lists and collections will complete the task, we can take advantage of a
method like map()
to organize and optimize our code into building blocks
of functions, which we can then chain together to create more readable and
understandable functions.
map()
Method Works
Define How the Array.prototype.map()
is an array method that iterates over all elements,
allowing you to apply a function to each element in that array, and changing
them into something else. The result is then returned as a new array, leaving
the original array unmodified (but remember, not the elements we modify, that
requires defensive copying). This is super important, because it saves us from
having to create a new array ourselves and copy stuff in there, or modifying
the original elements in the array, which we may need later.
map()
With Array
s
Demonstrate We use map()
when we want to perform an action on each element in the collection,
and "gather" the results into a new Array
.
We'll also use this as a chance to demonstrate some of the power of functions in
JavaScript. We'll write map()
four times so you can see how the iterator
functions allow us to write more expressive code.
for
and for...of
In this example, we are using a standard bit of iteration code. Because
for
and for...of
are general functions that can be used to do lots
of things another programmer won't be sure if the inner workings return
values are important or not.
let students = ["harry", "ron", "hermione", "ginevra"];
let rollCall = [];
for (const student of students) {
rollCall.push( student + " the wizard" );
}
//=> rollCall = ["harry the wizard", "ron the wizard", "hermione the wizard", "ginevra the wizard"];
When we write .map()
we are saying to other programmers: "Expect a new array
to come out of this after each element is touched!"
map()
With a Function Declaration
function studentRollCall(student) {
return student + " the wizard";
}
let students = ["harry", "ron", "hermione", "ginevra"];
let rollCall = students.map(studentRollCall);
//=> rollCall = ["harry the wizard", "ron the wizard", "hermione the wizard", "ginevra the wizard"];
With map()
, we have a list of n things and want that list of n things
to be transformed. Here, we're passing a function as an argument. Arguments
can be things like Number
or String
, but, in JavaScript, can also be
work. Very few other programming languages allow that!
The iterator function map()
expects to be passed a function as an
argument which they will hand each of their elements off to. In the case of
map()
it hands each element to the function and stores the return value of
the function into a new Array
.
This code is more expressive because it lives up to the promise of map. It
creates a new Array
after each element is "touched" by a function.
One drawback to this code is that the studentRollCall
function doesn't do
much work. It just returns something that the student
already knew how to
do. What if we use a function expression ("anonymous function") instead?
map()
With a Function Expression
let students = ["harry", "ron", "hermione", "ginevra"];
let rollCall = students.map(function(student) {
return student + " the wizard";
});
//=> rollCall = ["harry the wizard", "ron the wizard", "hermione the wizard", "ginevra the wizard"];
That's much shorter. It has all the same advantages of the previous version.
map()
With an Arrow Function
Thanks to arrow functions, we can shorten up the function expression to:
// When the parameter list is only one element, we can drop () !
let students = ["harry", "ron", "hermione", "ginevra"];
let rollCall = students.map( student => student + " the wizard" )
//=> rollCall = ["harry the wizard", "ron the wizard", "hermione the wizard", "ginevra the wizard"];
The code now fits on one line! There is much less noisy JavaScript code so
the expressiveness has increased: "rollCall
is the result of map
-ing
students
.
For the rest of of these examples, we'll use the arrow function.
map()
With Complex Data Structures
Demonstrate Let's use the map()
function on a trickier data structure — a list of robots.
To start things off, we have an array of robots. Now, let's activate all of
them. An activated robot needs to be marked as such using the isActivated
boolean, as well as have its number of modes doubled:
const robots = [
{ name: 'Johnny 5', modes: 5, isActivated: false, },
{ name: 'C3PO', modes: 3, isActivated: false, },
{ name: 'Sonny', modes: 2.5, isActivated: false, },
{ name: 'Baymax', modes: 1.5, isActivated: false, },
];
const activatedRobots = robots.map(function (robot) {
return Object.assign({}, robot, {
modes: robot.modes * 2,
isActivated: true,
});
});
console.log(activatedRobots);
/*
Result:
[
{ name: 'Johnny 5', modes: 10, isActivated: true },
{ name: 'C3PO', modes: 6, isActivated: true },
{ name: 'Sonny', modes: 5, isActivated: true },
{ name: 'Baymax', modes: 3, isActivated: true }
]
*/
With the native map()
function that is a property of Array
's prototype,
it gives us the exact same result! Now that we know how map is implemented,
it holds no more secrets for us! We can discard our own map()
function and
just use the map()
property on arrays.
map()
to Generate a New Array
Use Let's put our newly acquired knowledge of map()
to use! We just uploaded 10 coding
tutorials online, but some of them have inconsistent casing. We want all the titles
to be "title case", in other words, the first letter of each word is capitalized.
Create a new array with the new names of each tutorial that is in the proper title
case formatting.
For example, what does the this keyword mean?
should become What Does The This Keyword Mean?
.
const tutorials = [
'what does the this keyword mean?',
'What is the Contutorialuctor OO pattern?',
'implementing Blockchain Web API',
'The Test Driven Development Workflow',
'What is NaN and how Can we Check for it',
'What is the difference between stopPropagation and preventDefault?',
'Immutable State and Pure Functions',
'what is the difference between == and ===?',
'what is the difference between event capturing and bubbling?',
'what is JSONP?'
];
Run learn
and ensure that tests are passing.
Conclusion
map()
takes 2 arguments--a callback and the optional context. The callback runs
for each value in an array and returns each new value in the resulting array. It
returns a new array that is the same length as the original array and saves time
while making the code simpler and easy to read.