JavaScript Higher-Order Functions: A Beginner's Guide.
Exploring JavaScript Higher-Order Functions: A Step-by-Step Tutorial for New Programmers
In this article, we will discuss higher-order functions and callback functions in JavaScript, including why and how to use them. Before then, let’s define what higher-order functions are:
A higher-order function is any function that takes one or more functions as an argument (parameter) or returns a function as its result. The argument taken is called a “callback” function.
Any function that meets any of these conditions is referred to as a higher-order function in JavaScript. We have a few of them, but we will focus on the commonly used higher-order functions.
Prerequisite
I expect you to have basic JavaScript knowledge. If that sounds like you, then you are good to go.
Why higher-order functions?
Higher-order functions are inherent in functional programming, and serve numerous use cases. And to mention a few:
Modularity: Higher-order functions help break down complex tasks into small chunks or modules, making our code more maintainable.
Data abstraction: Higher-order functions can help us hide implementation methods and data that the user doesn’t need to see.
Code Readability: Using higher-order functions helps in writing code that is easy to read and understand.
Callback functions
Callback functions are functions that are passed as arguments to other functions. They are intended to be called at a later time to perform a specific operation. See the example below:
function processArray(array, callback) {
for (let i = 0; i < array.length; i++) {
callback(array[i]); // callback function that loops through each element in the array.
}
}
// Array of data
const data = [1, 2, 3, 4, 5];
// Callback function to display each element
function displayElement(element) {
console.log(element);
}
// Call the processArray function with the data and the displayElement callback
processArray(data, displayElement);
What did we do?
function processArray(array, callback) {
for (let i = 0; i < array.length; i++) {
callback(array[i]);
}
}
First, we declared a higher-order function,
processArray()
that takes an array and a callback function as an argument.Inside the function is a for loop that iterates through each element in the array.
For each element, the callback function is called, passing the current element as an argument.
const data = [1, 2, 3, 4, 5];
- This line defines an array of numbers.
function displayElement(element) {
console.log(element);
}
displayElement()
is a callback function. It takes an argument element
and logs it to the console.
processArray(data, displayElement);
Here, the processArray()
is called with two arguments:
data
: The array of numbers declared above.displayElement
: The callback function to be applied to each element in thedata
array.
processArray(data, displayElement);
In summary, the function processArray()
iterates through the data
array and passes each value to the displayElement()
function. As a result, each element of the data
array is logged on the console.
We just looked at an example of a higher-order function above. However, this is not all there is to higher-order functions. From the definition of higher-order functions, you would understand that a function taking another function as its argument is not the only criterion that makes for a higher-order function.
Cases where a function returns another function as its result also make a function a higher-order function. The returned function is referred to as a "closure". Take for instance:
function outerFunction(x) {
// The outer function defines and returns an inner function.
return function innerFunction(y) {
// The inner function uses the 'x' parameter from the outer function.
return x + y;
};
}
// Creating a closure by calling the outer function with an argument.
const addFive = outerFunction(5);
// Use the closure to add 5 to a value.
console.log(addFive(10)); // Output: 15
The outerFunction()
is a higher-order function because it returns an innerFunction()
which sums the values in each parameter.
While the examples above are custom higher-order functions, JavaScript provides built-in higher-order functions that are used to manipulate and transform data. Let’s take a look at some of them.
Map Method.
map()
is a built-in JavaScript higher-order function that is used to transform array elements based on custom logic. It takes a callback function that performs a specified task.
const users = [
{
id: 1,
username: 'Johndoe',
firstName: 'John',
lastName: 'Doe',
email: 'John.doe@example.com',
},
{
id: 2,
username: 'Janedoe',
firstName: 'Jane',
lastName: 'Doe',
email: 'Jane.doe@example.com',
},
{
id: 3,
username: 'Alice',
firstName: 'Alice',
lastName: 'Johnson',
email: 'alice.Johnson@example.com',
},
];
const mappedArray = users.map((user) => {
return user.username;
});
console.log(mappedArray); // logs: [Johndoe, Janedoe, Alice].
In this example, (user) ⇒ { return user.username; })
is a callback function passed to the map
method. The map method applies a function to an array and creates a new array with the result of the function calls.
Filter Method
Filter is another higher-order function that creates a new array based on a specified condition. It filters an array based on the provided conditions and returns a new array with the filtered result. In other words, It creates a new array for which the callback function returns true.
const users = [
{
id: 1,
username: 'Johndoe',
firstName: 'John',
lastName: 'Doe',
email: 'John.doe@example.com',
},
{
id: 2,
username: 'Janedoe',
firstName: 'Jane',
lastName: 'Doe',
email: 'Jane.doe@example.com',
},
{
id: 3,
username: 'Alice',
firstName: 'Alice',
lastName: 'Johnson',
email: 'alice.Johnson@example.com',
},
];
const filteredArray = users.filter((user) => {
return user.lastName === 'Johnson';
});
console.log(filteredArray);
// logs: 👇
/*
email: 'alice.Johnson@example.com';
firstName: 'Alice';
lastName: 'Johnson';
username: 'Alice';
*/
As you can see in the code above, filter
looped through the users
object and returned a new element for which the callback function was true. The callback function in this case is: (user) => { return user.lastName === 'Johnson'}
.
Reduce Method
Reduce on the other hand is a higher-order function that takes an array of values and reduces them to a single value. It takes two values which are a callback function and an optional initial value.
The callback contains an "accumulator" and "current" value argument, the accumulator is initialized to the initial value or the first element of the array if the initial value is not provided. The value of each iteration is added to the accumulator which is then passed to the current value.
const users = [
{
id: 1,
username: 'Johndoe',
firstName: 'John',
lastName: 'Doe',
email: 'John.doe@example.com',
age: 20,
},
{
id: 2,
username: 'Janedoe',
firstName: 'Jane',
lastName: 'Doe',
email: 'Jane.doe@example.com',
age: 30,
},
];
const ReducedArray = users.reduce((acculator, currentValue) => {
return acculator + currentValue.age;
}, 0); // Zero(0) is the initial value here.
console.log(ReducedArray); // logs: 50
Here, the reduce method was used alongside a callback function (acculator, currentValue) => { return acculator + currentValue.age;}
to sum all values of the ages in the array of objects.
Conclusion.
We just went over what higher-order and callback functions are and how to use them. However, there are other higher-order functions in JavaScript like (forEach(), sort(), every()
). They are not so different from the ones we covered, syntax-wise! Understanding callback functions will help a great deal in your coding career, so ensure to maximize their usage.
If you like this article, follow me for more. Thanks for reading and don’t forget to comment on the article 😊.