Explore practical examples of higher-order functions in JavaScript to simplify complex tasks like data processing. Learn through coding exercises and solutions.
In this section, we’ll delve into practical examples of higher-order functions in JavaScript. Higher-order functions are a powerful feature that can greatly simplify complex tasks, such as data processing, by allowing us to write more modular and reusable code. We’ll explore how to implement these functions in real-world scenarios, provide exercises to practice, and offer solutions for self-assessment.
Before we dive into examples, let’s briefly recap what higher-order functions are. A higher-order function is a function that can take other functions as arguments or return them as results. This capability allows us to create more abstract and flexible code.
Let’s start with a common task: filtering data. Suppose we have an array of objects representing people, and we want to filter out those who are adults (age 18 and above).
// Array of people
const people = [
{ name: 'Alice', age: 17 },
{ name: 'Bob', age: 22 },
{ name: 'Charlie', age: 15 },
{ name: 'David', age: 30 }
];
// Higher-order function to filter adults
function filterAdults(people, callback) {
return people.filter(callback);
}
// Callback function to check if a person is an adult
function isAdult(person) {
return person.age >= 18;
}
// Using the higher-order function
const adults = filterAdults(people, isAdult);
console.log(adults);
In this example, filterAdults
is a higher-order function that takes an array of people and a callback function isAdult
. It uses the filter
method to return only those people who meet the criteria defined in isAdult
.
Next, let’s look at transforming data. Imagine you have an array of numbers, and you want to square each number.
// Array of numbers
const numbers = [1, 2, 3, 4, 5];
// Higher-order function to transform numbers
function transformNumbers(numbers, callback) {
return numbers.map(callback);
}
// Callback function to square a number
function square(number) {
return number * number;
}
// Using the higher-order function
const squaredNumbers = transformNumbers(numbers, square);
console.log(squaredNumbers);
Here, transformNumbers
is a higher-order function that takes an array of numbers and a callback function square
. It uses the map
method to apply the transformation to each number.
Reducing data is another common task. Let’s say we want to calculate the total age of all people in our array.
// Higher-order function to reduce data
function totalAge(people, callback, initialValue) {
return people.reduce(callback, initialValue);
}
// Callback function to sum ages
function sumAges(total, person) {
return total + person.age;
}
// Using the higher-order function
const total = totalAge(people, sumAges, 0);
console.log(total);
In this example, totalAge
is a higher-order function that uses the reduce
method. It takes an array of people, a callback function sumAges
, and an initial value for the total age.
Function composition is a powerful technique that allows us to combine simple functions to create more complex operations. Let’s compose functions to first double a number and then square it.
// Function to double a number
function double(number) {
return number * 2;
}
// Function to compose two functions
function compose(f, g) {
return function(x) {
return f(g(x));
};
}
// Composing double and square
const doubleThenSquare = compose(square, double);
// Using the composed function
const result = doubleThenSquare(3);
console.log(result);
In this example, compose
is a higher-order function that takes two functions f
and g
and returns a new function that applies g
to its argument and then f
to the result.
Sorting data with custom criteria is another practical use of higher-order functions. Let’s sort our array of people by age.
// Higher-order function to sort data
function sortByAge(people, callback) {
return people.sort(callback);
}
// Callback function to compare ages
function compareAges(personA, personB) {
return personA.age - personB.age;
}
// Using the higher-order function
const sortedPeople = sortByAge(people, compareAges);
console.log(sortedPeople);
Here, sortByAge
is a higher-order function that uses the sort
method with a custom comparison function compareAges
.
Now it’s your turn! Try modifying the examples above to:
function isUnderage(person) {
return person.age < 18;
}
const underagePeople = filterAdults(people, isUnderage);
console.log(underagePeople);
function cube(number) {
return number * number * number;
}
const cubedNumbers = transformNumbers(numbers, cube);
console.log(cubedNumbers);
function averageAge(people) {
const total = totalAge(people, sumAges, 0);
return total / people.length;
}
const average = averageAge(people);
console.log(average);
const squareThenDouble = compose(double, square);
const result2 = squareThenDouble(3);
console.log(result2);
function compareNames(personA, personB) {
return personA.name.localeCompare(personB.name);
}
const sortedByName = sortByAge(people, compareNames);
console.log(sortedByName);
To better understand function composition, let’s visualize it using a flowchart.
graph TD; A[Input Number] --> B[Function g: double] B --> C[Function f: square] C --> D[Output Result]
Caption: This flowchart illustrates the process of composing two functions, double
and square
, to transform an input number.
Remember, mastering higher-order functions is a journey. As you practice and experiment with these concepts, you’ll find new ways to simplify and enhance your code. Keep exploring, stay curious, and enjoy the process of becoming a more proficient JavaScript developer!