JavaScript Map Function Explained - A Deep Dive
The built-in JavaScript map function returns a new array, where each element in the new array is the result of the corresponding element in the old array after being passed through a callback function. Later in the article, we’ll do a deep dive into some more advanced concepts regarding the map function and its uses.
Map Function Syntax
Example Usage
let newArray = oldArray.map(function callback(currentValue, index, array) {
// return element for new_array
}, thisArg);
The Array object’s built-in map method takes a function definition as its first parameter. The function whose definition we pass in will have 3 arguments available to it and will be called for each element in the original array. Each return value that the function creates will be the elements for the new array.
For instance, a simple example would look like:
const oldArray = [1, 4, 9, 16];
function double(val, index, arr) {
return val * 2;
}
const newArray = oldArray.map(double);
// newArray = [2, 8, 18, 32]
There is also an optional second parameter to the map function that we will go over later, a way to override this.
Syntactic Sugar
In the above example, to double each value in the original array, we only used the val argument. It’s extremely common to only care about the val argument in the map function. When that’s all we need we can simplify the syntax, and even throw in some es6 arrow functions:
const oldArray = [1, 4, 9, 16];
const double = (arr) => arr * 2;
const newArray = oldArray.map(double);
// newArray = [2, 8, 18, 32]
By only specifying one argument in our function definition, the interpreter will only give our function the val parameter, which is okay if it’s the only thing we care about.
We can also use an anonymous function, which means defining the function in the map’s input instead of giving it a name. This keeps our code clean and readable (assuming we don’t need to reuse the callback function elsewhere)
const oldArray = [1, 4, 9, 16];
const newArray = oldArray.map((arr) => arr * 2);
// newArray = [2, 8, 18, 32]
Index Parameter
If you remember from earlier, the callback function definition has a second parameter, the index:
function callback(currentValue, index, array)
By using the index parameter we can do some more interesting calculations based on the position in the array:
const oldArray = [1, 4, 9, 16];
const newArray = oldArray.map((val, index) => {
return val * index;
});
// newArray = [0, 4, 18, 48]
Array Parameter
The third and final parameter made available to our callback is a copy of the original array. This can be useful if we care about more than just the value or index that we are currently operating on. We can look forward or backward in the array and use other elements as part of our mapping:
const oldArray = [16, 9, 4, 1];
const newArray = oldArray.map((val, index, arr) => {
let nextItem = index + 1 < arr.length ? arr[index + 1] : 0;
return val - nextItem;
});
// newArray = [7, 5, 3, 1]
Overriding ‘This’
The map function has an often-overlooked optional second parameter. We can provide an object that will become ’this’ within the scope of our callback.
let newArray = oldArray.map(callbackFunction, thisArg);
For example, maybe we have a callback that is used in other places in our code, and we want to reuse it, but we just need to change the environment it operates in:
const oldArray = [1, 4, 9, 16];
function ourFunc(val, index, arr) {
return val * this.windowSize;
}
const newArray = oldArray.map(ourFunc, { windowSize: 10 });
// newArray = [10, 40, 90, 169]
Now we can reuse that callback, but change its parameters by modifying ’this'.
Using .map() in React
It’s super common in React.js or Vue.js to need to render a list of data on a page, and the .map() method is a great way to do it. This Scrimba post gives us a great example:
const heroes = ["Superman", "Batman", "Wonder Woman"];
const Headings = () => {
const headings = heroes.map((hero, index) => <h1 key={index}>{hero}</h1>);
return <header>{headings}</header>;
};
Related Articles
Which Method of Iteration in JavaScript is Fastest?
Nov 08, 2019 by Lane Wagner - Boot.dev co-founder and backend engineer
There are many ways to traverse an array in Javascript. In this benchmark, we will look at five different ways and the pros and cons of each. Keep in mind that these benchmarks were run in a Chrome browser on Codepen.io. Results will vary by browser/interpreter.
Singletons in ES6 - The Good, The Bad, The Ugly
Nov 04, 2019 by Lane Wagner - Boot.dev co-founder and backend engineer
Singletons are fairly controversial as far as I can tell, especially in JavaScript programming. Let’s take a look at what they are, when to (maybe) use them, and when not to.
How to Recursively Traverse JSON Objects
Sep 22, 2019 by Lane Wagner - Boot.dev co-founder and backend engineer
I’ve found that it’s pretty rare that I need recursion in application code, but every once in a while I need to write a function that operates on a tree of unknown depth, such as a JSON object, and that’s often best solved recursively. Even though recursion is rare, it is important to recognize when a problem is best solved recursively so that we can implement a good solution when the time comes.
Secure Random Numbers in Node.js
Jul 03, 2019 by Lane Wagner - Boot.dev co-founder and backend engineer
Quick answer: use crypto.randomBytes() for cryptographically secure randomness in Node.js. const { randomBytes } = await import("node:crypto"); const buf = randomBytes(256); console.log(`${buf.length} bytes of random data: ${buf.toString("hex")}`); crypto.randomBytes() is a cryptographically secure random number generator based on openssl. Depending on the operating system of the user, randomBytes will use /dev/urandom (Unix) or CryptoGenRandom (Windows).