Array methods such as forEach()
, map()
and filter()
are some of the Higher Order Array Functions that come in very handy when you have to work with data that's in an Array.
In this article we'll be discussing the following Higher-Order Functions, with examples :
forEach()
map()
filter()
I'll be assuming that you have a basic understanding of what Higher-Order Functions are and how to work with them, if not, I recommend you read my previous article on it.
Understanding Higher Order Functions in JavaScript.
Anil Seervi ・ Dec 4 '21
Array.forEach()
forEach()
method is very useful to perform certain operation(s) for every element in the Array.
The forEach()
method on an Array executes the provided callback function for each element in the array in ascending index(starting 0).
Syntax
forEach(callbackFn)
forEach((element, index, array) => { /* ... */ } )
Parameters
callbackFn
Function to execute on each element. It accepts one to three arguments :
element
: The current element being processed in the array.
index
(optional) : The index of element
in array.
array
(optional) : The array on which forEach()
was called upon.
The forEach()
method doesn't return anything : undefined
If you look at the signature of the callback function in this method, it looks similar to the forEach()
function that I created in the previous Higher-Order Functions article.
Understanding Higher Order Functions in JavaScript.
Anil Seervi ・ Dec 4 '21
Examples
Let's recreate the same example now using the Array.forEach()
method :
const numbs = [5, 9, 10, 1] // Array of numbers
numbs.forEach((n, i, arr) => { // n => element, i => index, arr => array(numbs)
arr[i] = n + 2 // add 2 to current element
})
numbs.forEach((n) => console.log(n)) // logs all element one-by-one
// 7
// 11
// 12
// 3
As the forEach()
is a method on the array itself, we can call it on any array using the dot notation.
In the above example we've called Array.forEach()
Higher-Order function twice with arrow functions as callbacks, defined right withing forEach()
's parameters.
Say we have an Array of full names and you are required to separate all the full names into firstName
and lastName
of an object and push them into an array that already contains same kind-of data. How'd you do it?
const fullNames = ["Adam Benson","Clare Donaldson","Ben Adams","Donald Clarkson"]
Here's how you can use the forEach()
to push objects containing firstName
and lastName
property to the names
array.
const names = [ { firstName: 'Anil', lastName: 'Seervi' } ]
fullNames.forEach((n) => {
const obj = {} // empty object for initialization
[obj.firstName, obj.lastName] = n.split` ` // split at spaces and destructure initialize
names.push(obj) // push the object to names array
})
console.log(names)
/*
[
{ firstName: 'Anil', lastName: 'Seervi' }
{ firstName: 'Adam', lastName: 'Benson' },
{ firstName: 'Clare', lastName: 'Donaldson' },
{ firstName: 'Ben', lastName: 'Adams' },
{ firstName: 'Donald', lastName: 'Clarkson' }
]
*/
In the above example, within our callback, we create an empty object obj
to store the properties. Then we split the current element of the array at spaces, destructure it right away storing it to properties firstName
and lastName
in the object obj
. At last we push the object into the names
array.
Array.map()
Array.map()
method comes very handy when you have to create a new array from executing a certain function on an existing array.
The Array.map()
method on an Array returns a new array populated with the return value of the callback function called for every element in an array in ascending index(starting 0).
Syntax
map(callbackFn)
map((element, index, array) => { /* ... */ } )
// returns a new array populated with results of callbackFn
Parameters
callbackFn
Function to execute on each element of arr
. Each time callbackFn
executes, the return value is added to the newArray
.
It accepts one to three arguments :
element
: The current element being processed in the array.
index
(optional) : The index of element
in array.
array
(optional) : The array on which map()
was called upon.
Return value
The map()
method returns a new Array with each element being the result of the callback function.
Examples
Let's assume we are given the following array and are told to produce another array of consisting of the sqaures of all the respective elements.
const numbs = [5, 9, 10, 1] // our boring array of numbers
The easiest way to do this will be by using the Array.map()
method :
const squares = numbs.map(n => n ** 2)
// Yes, its easy as that!!
console.log(numbs)
// [ 5, 9, 10, 1 ]
console.log(sqaures)
// [ 25, 81, 100, 1 ]
That was so easy right. All we need to do is to call the map()
method on our numbs
array and return the square of the current element within it for our logic. As the map()
method itself returns a new Array, we store it in the variable sqaures
.
Now let's look at another example where we'll convert an array of objects with firstName
and lastName
properties that we got as our output in the forEach()
and create another array which will consist of only full names. Kinda the reverse of what we did in forEach()
example.
// array of objects with firstName and lastName
const names = [
{ firstName: 'Anil' },
{ firstName: 'Adam', lastName: 'Benson' },
{ firstName: 'Clare', lastName: 'Donaldson' },
{ firstName: 'Ben', lastName: 'Adams' },
{ firstName: 'Donald', lastName: 'Clarkson' },
]
// create a new Array of fullNames using names Array
const fullNames = names.map((name) => {
const full_name = `${name.firstName} ${name?.lastName || ""}`
return full_name.trimEnd()
})
console.log(fullNames)
// [ 'Anil', 'Adam Benson', 'Clare Donaldson', 'Ben Adams', 'Donald Clarkson' ]
Above, the first thing you'll notice while looking at the example is we don't have lastName
property for my name and our logic will have to handle that too.
Within the callback of our map()
method we are using template literals to concatenate firstName
and lastName
(if any: using optional chaining) to form the full_name
. And returning trimmed full_name
from the callback.
Array.filter()
As the name implies, this method is used to filter out the array which meets a certain condition.
Array.filter()
method on the Array returns an new Array with only the elements that pass the test condition within the callback function.
Syntax
filter(callbackFn)
filter((element, index, array) => { /* ... */ })
// returns a new array with elements that satisfy the callback condition.
Parameters
callbackFn
Function is a predicate to execute on each element of arr
. Each time callbackFn
is called, only the element
's that coerce to true
are added into the new Array.
It accepts one to three arguments :
element
: The current element being processed in the array.
index
(optional) : The index of element
in array.
array
(optional) : The array on which filter()
was called upon.
Return Value
The filter()
method returns a new Array with only the elements that satisfy the test condition in the callbackFn
.
Examples
To keep it easier to understand I'm taking our same old numbs
array to work on.
const numbs = [5, 9, 10, 1, 6, 3] // hey, I'm bigger this time :)
lets pose a couple question so to filter
our boring array.
Q1. Obtain an array of Odd Numbers from numbs
const odd = numbs.filter(n => n % 2 !== 0)
console.log(odd)
// [ 5, 9, 1, 3]
Within the callback, we return true only for odd numbers in our array which in-turn returns all odd numbers in our numbs
array.
Q2. Obtain an array of Prime Numbers from numbs
function isPrime(numb) {
for (let i = 2, s = Math.sqrt(numb); i <= s; i++)
if (numb % i === 0) return !1
return numb > 1
}
console.log(numbs.filter(isPrime))
// [ 5, 3 ]
Here isPrime
is our callback for filter
method which gets called with every element in numbs
and acts as our condition to filter out numbers that are prime.
Below is a composite example of both map()
and filter()
methods. I'm going to create an Array that'll contain names of my GitHub Repos which are majorly written with SCSS.
The example is an async IIFE
(Immediately Invoked Function Expression) Function that'll get called as soon as it's defined. Within our async function, I'm fetching the data related to my GitHub repos in JSON format using GitHub's REST API.
The API returns an Array of Objects that contain information about my public GitHub repositories listed alphabetically. You can see the response of the API by visiting the below URL:
- Maximum of 30 repos: https://api.github.com/users/AnilSeervi/repos
- All the repos : https://api.github.com/users/anilseervi/repos?per_page=100
The API only returns a maximum of 30 repos without any query parameters.
(async function jsRepos() {
const res = await fetch("https://api.github.com/users/AnilSeervi/repos?per_page=100") // fetch the JSON from API
const data = await res.json() // parse JSON to JavaScript Object
const filterJSRepos = data.filter(i => i.language === "SCSS") // filter the Repos based on language
const repoNames = filterReposData.map(i => i.name) // Create an array of filtered Repo names
console.log(repoNames)
// ['DevFolio', 'mdn-minimalist', 'ts-portfolio']
})()
The response(in JSON) fetched from the URL is stored in res
and then converted to a JavaScript Object that is stored in data
.
Note: The names and number of repos may change based on the time you are reading this.
Now we have an Array of objects of all the repos which we need to be filtered based on the language
property. Objects whose language property is SCSS
are filtered into filterJSRepos
constant.
After filtering the Repos, we can now grab just the name
property of the filtered Repos using map()
and voila, there's our array that contains the names of my repos those majorly contain SCSS.
I hope this article helped you understand the Higher-Order Array Functions(forEach()
, map()
, filter()
).
Thank you for reading, let's connect!
Thank you for reading my blog. Feel free to ask questions and leave any comments down here and, let's connect on Twitter!
Top comments (0)