Learn how `Array.map` and `Array.filter` work by learning how to write them yourself. We'll see what makes these functions so powerful and how they allow us to work efficiently with large amounts of data. You'll use these functions thousands of times in your JavaScript career.

Master Map & Filter, Javascript’s Most Powerful Array Functions

Learn how Array.map and Array.filter work by writing them yourself.

These functions allow us to manipulate data effectively and efficiently. They’re meant to copy an array and change it a little bit in the process. You’ll be using them for the rest of your JavaScript career.

Array.map

Array.map is meant to transform one array into another by performing some operation on each of its values. The original array is left untouched and the function returns a reference to a new array.

For example, say we have an array of numbers and we want to multiply each number by three. We also don’t want to change the original array. To do this without Array.map, we can use a standard for-loop.

for-loop

Press + to interact
var originalArr = [1, 2, 3, 4, 5];
var newArr = [];
for(var i = 0; i < originalArr.length; i++) {
newArr[i] = originalArr[i] * 3;
}
console.log(newArr); // -> [3, 6, 9, 12, 15]

Simple enough. Let’s abstract this loop into its own function so that we can turn any array we like into a new array with each element multiplied by 3. In other words, we’re trying to write a function that will take in an any array ([1, 2, 3]) and spit out a brand new array with its numbers multiplied by three ([3, 6, 9]).

All we have to do is take the code we wrote above and turn it into a function so that we can reuse that loop over and over. This might seem difficult, but try to get through it.

Multiply by three

Press + to interact
var originalArr = [1, 2, 3, 4, 5];
function multiplyByThree(arr) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = arr[i] * 3;
}
return newArr;
}
var arrTransformed = multiplyByThree(originalArr);
console.log(arrTransformed); // -> [3, 6, 9, 12, 15]

Beautiful. Now we can pass any array into multiplyByThree and get a new array out with its values multiplied. Now, we’re going to add some code that might seem useless, but bear with me here.

Let’s take a single line in that function — line 7 — and turn it into its own function as well. The result will be code that is equivalent to that in the block above, but we’ll need it this way right after.

Press + to interact
var originalArr = [1, 2, 3, 4, 5];
function timesThree(item) {
return item * 3;
}
function multiplyByThree(arr) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = timesThree(arr[i]);
}
return newArr;
}
var arrTransformed = multiplyByThree(originalArr);
console.log(arrTransformed); // -> [3, 6, 9, 12, 15]

This block does the same exact thing as the one before it. It just takes one piece out and turns it into its own function.

What if we wanted to multiply all items in an array by 5? or 10? Would we want to make a new looping function for each of those? No, not at all. That would be tedious and repetitive.

Multiply by anything

Let’s change the multiplyByThree code to be able to multiply by anything. Let’s rename it to just multiply. This is the hardest part and might take some time to wrap your head around, but try to get through it. Afterwards, it’s easy.

We’re turning this:

Press + to interact
function multiplyByThree(arr) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = timesThree(arr[i]);
}
return newArr;
}

Into this. Differences are on lines 1 and 5.

Press + to interact
function multiply(arr, multiplyFunction) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = multiplyFunction(arr[i]);
}
return newArr;
}

We’ve renamed the function and given it an extra argument to take in. That argument itself will be a callback function. Now, we’re passing a function in to multiply ourselves, telling multiply how we want each item transformed. Using our brand new function, let’s multiply by 3 again.

Press + to interact
function multiply(arr, multiplyFunction) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = multiplyFunction(arr[i]);
}
return newArr;
}
var originalArr = [1, 2, 3, 4, 5];
function timesThree(item) {
return item * 3;
}
var arrTimesThree = multiply(originalArr, timesThree);
console.log(arrTimesThree); // -> [3, 6, 9, 12, 15]

We’re giving our multiply function the instructions it needs to transform each value in the array by passing in the timesThree function. What if we want to multiply by 5 instead? We just give it different instructions, or a different function.

Press + to interact
var originalArr = [1, 2, 3, 4, 5];
function timesFive(item) {
return item * 5;
}
var arrTimesFive = multiply(originalArr, timesFive);
console.log(arrTimesFive); // -> [5, 10, 15, 20, 25]

It’s as simple as swapping out the timesThree function for a timesFive function. Repeating this technique, we can multiply by any number we want — we just write a new, very simple function. With one single for-loop, we can multiply an array by whatever we want.

Map

Let’s make multiply even more powerful. Instead of multiplying by something, let’s allow the function to transform our array any way we want. Let’s rename multiply to, oh, I don’t know… how about map? So, we’re turning this:

Press + to interact
function multiply(arr, multiplyFunction) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = multiplyFunction(arr[i]);
}
return newArr;
}

Into this.

Press + to interact
function map(arr, transform) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = transform(arr[i]);
}
return newArr;
}

Look closely at lines 1 and 5 and see what we changed between the multiply and map functions directly above. The only things we changed were the name of the function and the name of the second parameter that it takes in. That’s it. Turns out, multiply was already what we wanted, named differently.

We can pass in any function we want to map. We can do transform an array any way we want. Say we have an array of strings, and we want to turn them all uppercase:

Press + to interact
function map(arr, transform) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = transform(arr[i]);
}
return newArr;
}
function makeUpperCase(str) {
return str.toUpperCase();
}
var arr = ['abc', 'def', 'ghi'];
var ARR = map(arr, makeUpperCase);
console.log(ARR); // -> ['ABC', 'DEF, 'GHI']

We’ve effectively just written Array.map. Pretty neat, huh?

Using Array.map

How does the map function compare to the actual native Array.map? The usage is slightly different. Firstly, we don’t need to pass in an array as the first argument. Instead, the array used is the one to the left of the dot. As an example, the following two are equivalent. Using our function:

Press + to interact
function func(item) {
return item * 3;
}
var arr = [1, 2, 3];
var newArr = map(arr, func);
console.log(newArr); // -> [3, 6, 9]

Using the native Array.map, we don’t pass in the array. We call the Array.map method on our array and only pass in the function:

Press + to interact
function func(item) {
return item * 3;
}
var arr = [1, 2, 3];
var newArr = arr.map(func);
console.log(newArr); // -> [3, 6, 9]

More Array.map arguments

There’s a key difference we’ve skipped over. Array.map will provide your given function with an additional two arguments: the index, and the original array itself.

Press + to interact
function logItem(item) {
console.log(item);
}
function logAll(item, index, arr) {
console.log(item, index, arr);
}
var arr = ['abc', 'def', 'ghi'];
arr.map(logItem); // -> 'abc', 'def', 'ghi'
arr.map(logAll); // -> 'abc', 0, ['abc', 'def', 'ghi']
// -> 'def', 1, ['abc', 'def', 'ghi']
// -> 'ghi', 2, ['abc', 'def', 'ghi']

This allows us to use the index and the original array inside our transformation function if we choose. For example, say we want to turn an array of items into a numbered shopping list. We’d want to use the index:

Press + to interact
function numberItem(item, index) {
return (index + 1) + '. ' + item;
}
var arr = ['bananas', 'tomatoes', 'pasta', 'avocado'];
var mappedArr = arr.map(numberItem);
console.log(mappedArr);
// -> [ '1. bananas', '2. tomatoes', '3. pasta', '4. avocado' ]

Our complete map function should incorporate this functionality.

Press + to interact
function map(arr, transform) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr[i] = transform(arr[i], i, arr);
}
return newArr;
}

This short function is the essence of Array.map. The actual function will have some error-checking and optimizations, but this is its core functionality.

Lastly, of course, we can also write a function directly in the map call. Reworking our multiplyByThree example:

Press + to interact
var arr = [1, 2, 3, 4, 5];
var arrTimesThree = arr.map(function(item) {
return item * 3;
});
console.log(arrTimesThree); // -> [3, 6, 9, 12, 15]

Done. Phew.

widget

Array.filter

The idea here is similar to Array.map, except instead of transforming individual values, we want to filter existing values. Without any functions (besides Array.push), say we want to filter out values in an array that are less than 5:

for-loop

Press + to interact
var arr = [2, 4, 6, 8, 10];
var filteredArr = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] >= 5) {
filteredArr.push(arr[i]);
}
}
console.log(filteredArr); // -> [6, 8, 10]

Let’s abstract this to a function so we can remove values below 5 in any array.

Press + to interact
var arr = [2, 4, 6, 8, 10];
function filterLessThanFive(arr) {
var filteredArr = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] >= 5){
filteredArr.push(arr[i]);
}
}
return filteredArr;
}
var filteredArr = filterLessThanFive(arr);
console.log(filteredArr); // -> [6, 8, 10]

Let’s make it so we can filter out all values below any arbitrary value.

Press + to interact
function isGreaterThan5(item) {
return item > 5;
}
function filterLessThanFive(arr) {
var filteredArr = [];
for(var i = 0; i < arr.length; i++) {
if(isGreaterThan5(arr[i])) {
filteredArr.push(arr[i]);
}
}
return filteredArr;
}
var arr = [2, 4, 6, 8, 10];
var filteredArr = filterLessThanFive(arr);
console.log(filteredArr); // -> [6, 8, 10]

→ Abstracting out the filtering functionality

Press + to interact
function filterBelow(arr, greaterThan) {
var filteredArr = [];
for(var i = 0; i < arr.length; i++) {
if(greaterThan(arr[i])) {
filteredArr.push(arr[i]);
}
}
return filteredArr;
}
var originalArr = [2, 4, 6, 8, 10];

→ Filtering out anything below 5, using filterBelow

Press + to interact
function isGreaterThan5(item) {
return item > 5;
}
var newArr = filterBelow(originalArr, isGreaterThan5);
console.log(newArr); // -> [6, 8, 10];

→ Filtering out anything below 7, using filterBelow

Press + to interact
function isGreaterThan7(item) {
return item > 7;
}
var newArr2 = filterBelow(originalArr, isGreaterThan7);
console.log(newArr2); // -> [8, 10];

filter

So we have a function filterBelow that will filter out anything below a certain value, based on the greaterThan function we give it (this is identical to the filterBelow function above):

Press + to interact
function filterBelow(arr, greaterThan) {
var filteredArr = [];
for(var i = 0; i < arr.length; i++) {
if(greaterThan(arr[i])) {
filteredArr.push(arr[i]);
}
}
return filteredArr;
}

Let’s rename it.

Press + to interact
function filter(arr, testFunction) {
var filteredArr = [];
for(var i = 0; i < arr.length; i++) {
if(testFunction(arr[i])) {
filteredArr.push(arr[i]);
}
}
return filteredArr;
}

And we’ve written filter. It’s basically the same as Array.filter, again except for usage:

Press + to interact
var arr = ['abc', 'def', 'ghijkl', 'mnopuv'];
function longerThanThree(str) {
return str.length > 3;
}
var newArr1 = filter(arr, longerThanThree);
var newArr2 = arr.filter(longerThanThree);
console.log(newArr1); // -> ['ghijkl', 'mnopuv']
console.log(newArr2); // -> ['ghijkl', 'mnopuv']

Again, Array.filter passes in the index and the original array to our function.

Press + to interact
function log(item, index, arr) {
console.log(item, index, arr);
}
var arr = ['abc', 'def', 'ghi'];
arr.filter(log); // -> 'abc', 0, ['abc', 'def', 'ghi']
// -> 'def', 1, ['abc', 'def', 'ghi']
// -> 'ghi', 2, ['abc', 'def', 'ghi']

So we should make our function do the same.

Press + to interact
function filter(arr, testFunction) {
var filteredArr = [];
for(var i = 0; i < arr.length; i++) {
if(testFunction(arr[i], i, arr)) {
filteredArr.push(arr[i]);
}
}
return filteredArr;
}

Wow. That’s it. You’ve learned how to use and write Array.map and Array.filter.

Get hands-on with 1200+ tech skills courses.