## DEV Community is a community of 867,901 amazing developers

We're a place where coders share, stay up-to-date and grow their careers. Posted on • Updated on • Originally published at anuradha.hashnode.dev

# Higher-Order Functions In Javascript

Hello Developers!!👩‍💻👨‍💻 In this post, we'll learn about the important concept which makes Javascript suitable for functional programming, Higher-Order Functions. If you are a Javascript developer then you may have already used them without even knowing.

To fully understand the Higher-Order Functions, we first need to understand the concept of First Class Functions.

A programming language is said to have First-class functions when functions in that language are treated like any other variable. For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function, and can be assigned as a value to a variable.

If you are not aware of what First Class Functions is so I highly recommend you to read the previous article in this series about this topic for clear understanding.

• What is Higher-Order Functions
• built-in Higher-Order Methods
• Filtering arrays
• Transforming with map
• Summarizing with reduce
• Composability

Now, let's start our journey 🚀

## What is Higher-Order Functions 🧐?

Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.
Higher-order functions allow us to abstract over actions, not just values.

Let's try to understand this using an example:

Example 1: Functions that operate on other functions by returning them

``````function outer(a, b){
return function inner(){
return a * b;
}
}

``````

In the above example, the `outer()` function acts as a Higher-Order Functions by returning an another function `inner()`.

Example 2: Functions that operate on other functions by taking them as arguments

``````function multiplyFn(a,b){
return a * b;
}

// Higher Order Function
function displayResult(multiply){
for(let x = 1; x <= 10; x++){
console.log(multiply(x,x));
}
}

displayResult(multiplyFn);
``````

In the above code snippet, `displayResult` is a Higher-Order function that takes a `multiplyFn` as an argument and operates on them. Taking another function as an argument is often referred to as a callback function because it is called back by the higher-order function.

## Built-in Higher-Order Methods 🤓

Arrays provide a number of useful higher-order methods.

• You can use the `filter` method to returns a new array containing only the elements that pass the predicate function.
• Transforming an array by putting each element through a function is done with a `map`.
• You can use `reduce` to combine all the elements in an array into a single value.
• The `some` method tests whether any element matches a given predicate function.
• `findIndex` finds the position of the first element that matches a predicate.

These are some of the examples of Higher-Order Functions.

Higher-order functions allow you to write simpler and more elegant code.

Let’s take a look at some examples of built-in higher-order functions and see how it compares to solutions where we aren’t using Higher-Order Functions.

### Filtering arrays 📋

The `filter()` method creates a new array with all elements that pass the test implemented by the provided function.

Example 1: `filter()` Without Higher-Order Functions

``````let marks = [100, 200, 300, 400, 500];

let result = [];

for (let x = 0; x < marks.length; x++){
if(marks[x] > 300){
result.push(marks[x]);
}
}

console.log(result); // [400, 500]
``````

Example 2: `filter()` With Higher-Order Functions

``````let marks = [100, 200, 300, 400, 500];

let ans = marks.filter((item)=> item > 300)

console.log(ans); // [400, 500]

console.log(marks); // [100, 200, 300, 400, 500]
``````

Note how the filter function, rather than deleting elements from the existing array, builds up a new array with only the elements that pass the test. This function is pure. It does not modify the array it is given.

### Transforming with map 🔍

The `map()` method creates a new array by calling the callback function provided as an argument on every element in the input array. The `map()` method will take every returned value from the callback function and creates a new array using those values.

Example 1: `map()` Without Higher-Order Functions

``````let marks = [100, 200, 300, 400, 500];

let result = [];

for (let x = 0; x < marks.length; x++) {
result.push(marks[x] * 2);
}

console.log(result); // [200, 400, 600, 800, 1000]
``````

Example 2: `map()` With Higher-Order Functions

``````let marks = [100, 200, 300, 400, 500];

let result = marks.map((item) => item * 2);

console.log(result); // [200, 400, 600, 800, 1000]
``````

The `map` method transforms an array by applying a function to all of its elements and building a new array from the returned values. The new array will have the same length as the input array, but its content will have been mapped to a new form by the function.

### Summarizing with reduce 👩‍🏫

The `reduce()` method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

Example 1: `reduce()` Without Higher-Order Functions

``````let marks = [100, 200, 300, 400, 500];

let sum = 0;

for(let i=0; i< marks.length; i++){
sum += marks[i];
}

console.log(sum); // 1500
``````

Example 2: `reduce()` With Higher-Order Function

``````let marks = [100, 200, 300, 400, 500];

const reducer = (accumulator, currentValue) => accumulator + currentValue;

console.log(marks.reduce(reducer)); // 1500
``````

Your reducer function's returned value is assigned to the accumulator, whose value is remembered across each iteration throughout the array, and ultimately becomes the final, single resulting value.

💡💡The above code snippets show the advantages of the Higher-Order Function which made our code cleaner, more concise, and less verbose.

## Composability

Function composition is the process of combining two or more functions to produce a new function. Composing functions together is like snapping together a series of pipes for our data to flow through.

Higher-order functions start to shine when you need to compose operations.

Take a look at the following example:

``````let marks = [123, 456, 789, 3201, 6054, 987];

let reducer = (accumulator, currentValue) => accumulator + currentValue;

let average = grades => (
)

console.log(Math.round(average(marks.filter((item) => item > 500))));   // 2758
``````

In the above code snippet:

• Given an array of marks, we need to find the average of all the marks greater than 500.
• First, we apply a `filter()` method on marks array which gives us a new array containing marks greater than 500.
• Then we pass the above resultant array (containing marks greater than 500) to the `average()` method.
• `average()` method in turn uses the `reduce()` method to find out the sum of all the elements in an array and divides it with the total array's length to find out the average of marks.
• At last, we pass the above resultant number to `Math.round()` which yields our final result, i.e. 2758.

🤯🤯 That's too much work with a single line of code!!

If you are confused 😵😵 with the above example then take a look at the below code for a clear understanding.

``````let marks = [123, 456, 789, 3201, 6054, 987];

let reducer = (accumulator, currentValue) => accumulator + currentValue;

let average = grades => (
)

let marksGreaterThan500 = marks.filter((item) => item > 500);
console.log(marksGreaterThan500); // [789, 3201, 6054, 987]

let averageMarks = average(marksGreaterThan500);
console.log(averageMarks); // 2757.75

let roundOffResult = Math.round(averageMarks);
console.log(roundOffResult); // 2758
``````

I hope now you understand the power of Higher-Order Functions. This helps us to write down complex functionality with clean code that is easy to read, understand and debug.

Being able to pass function values to other functions is a deeply useful aspect of JavaScript. It allows us to write functions that model computations with “gaps” in them. The code that calls these functions can fill in the gaps by providing function values.

## Wrap Up !!

Thank you for your time !! Let's connect to learn and grow together.