How to understand Higher-order functions and Callbacks in JS

Arjun Vaidy
Nerd For Tech
Published in
4 min readDec 11, 2022

Before diving deep,

Let’s understand why we need functions in the first place.

Every code follows the DRY principle(Don’t Repeat Yourself). The bedrock of the DRY principle is Functions.

Let’s add two numbers, 10 and 20,

const sum1 = 10 + 20;

Let’s add 50 and 60,

const sum2 = 50 + 60

Sit back here and ask the question — Am I repeating myself here? What do we do?

As I said earlier, functions come to the rescue!

First, let us convert the above lines into functions.

function sum1() { 
return 10 + 20
}

Then,

function sum2() {
return 50 + 60
}

Hurrah! we have converted it into functions but wait and ask, ‘Are we using DRY here?’.

No, we are still repeating every addition of two numbers.

Just because you convert your code into functions doesn’t mean you followed the DRY principle.

DRY = Identifying what is changed and unchanged.

What is changing = Numbers.

What is unchanged = Addition operation.

We can insert unchanged patterns into the functions, but what about changing ones?

Unchanged = Inside the functions.

Changed = Welcome to Parameters.

function sum(a,b) {
return a + b // Addition inside the function
}

Here ‘a’ and ‘b’ are parameters that take care of changing one.

Hence invoking the functions using arguments.

const sum1 = sum(10,20)
const sum2 = sum(50,60)

Complicating a bit:

We will work on arrays.

We will add each element in the array by 5.

const arr = [1,2,3];

How to do?

We will loop through each element in the array and push the result into a new array.

const arr = [1,2,3];

function arrAddFive(inputArray) {
let output = [] // Initializing empty array
for(i=0;i<inputArray.length;i++) {
let addingFive = inputArray[i] + 5; // addingFive to each element
output.push(addingFive); // Pushing it to output array
}
return output // Returns the output array(contains added 5 element)
};

const addresult1 = arrAddFive(arr);
// [6,7,8]

For different arrays,

// Same code above
const addresult2 = arrAddFive([11,12,13]); // [16,17,18]
const addresult3 = arrAddFive([20,21,22]); // [25,26,27]

We use the same function for different arrays to align with DRY. Good!

We will do a different operation, say multiply by 5

const arr = [1,2,3];

function arrMultiplyFive(inputArray) {
let output = [] // Initializing empty array
for(i=0;i<inputArray.length;i++) {
let multiplyingFive = inputArray[i] * 5; // Multiply 5 to each element
output.push(multiplyingFive); // Pushing it to output array
}
return output // Returns the output array(contains added 5 element)
};

const mulresult1 = arrMultiplyFive(arr); // [5,10,15]

For different arrays,

const mulresult2 = arrMultiplyFive([11,12,13]) // [50,60,65]
const mulresult3 = arrMultiplyFive([20,21,22]) // [100,105,110]

Do we use DRY here? Of course, yes! because the same function is called for different arrays.

What if we want both multiplication and addition in the same code?

const arr = [1,2,3];

function arrAddFive(inputArray) {
let output = [] // Initializing empty array
for(i=0;i<inputArray.length;i++) {
let addingFive = inputArray[i] + 5; // adding 5 to each element
output.push(addingFive); // Pushing it to output array
}
return output // Returns the output array(contains added 5 element)
};

function arrMultiplyFive(inputArray) {
let output = [] // Initializing empty array
for(i=0;i<inputArray.length;i++) {
let multiplyingFive = inputArray[i] * 5; // Multiply 5 to each element
output.push(multiplyingFive); // Pushing it to output array
}
return output // Returns the output array(contains added 5 element)
};

const addresult1 = arrAddFive(arr);
const mulresult1 = arrMultiplyFive(arr);

Now tell me the answer, Are we following DRY footsteps here?

Partially yes! Because we use the same function for different arrays for the same operations.

When you want to add 5, irrespective of the array → we use ‘arrAddFive’ function.

When you want to multiply by 5 irrespective of the array → we use ‘arrMultiplyFive’ function.

But we don’t use the same function irrespective of array and operation(Multiplication or Addition).

We can say we’ve been using the functions in first order or lower order.

DRY is all about finding a common pattern:

We will see common patterns here for both functions,

Anything that changes(Differ) will be passed as parameters to the function.

What changes?

let multiplyingFive = inputArray[i] * 5;
let addingFive = inputArray[i] + 5;

Can we put same a parameter like this,

// Don't do this
const mulresult1=arrFunction(multiplyingFive=InputArray[i]*5,inputArray)

I know it's silly, but there is a point I would like to make.

I can create a function that always returns the input number multiplied by 5 or adds 5.

Let me code this,

const arr = [1,2,3];

function arrFunc(callBackFn,inputArray) {
let output = [] // Initializing empty array
for(i=0;i<inputArray.length;i++) {
output.push(callBackFn(inputArray[i])); // Invoking the callBackFn
}
return output // Returns the output array(contains added 5 element)
};

function multiplyFive(input) {
return input * 5;
}

function addingFive(input) {
return input + 5;
}

const addresult1 = arrFunc(multiplyFive,arr); // [6,7,8]
const mulresult1 = arrFunc(addingFive,arr); // [5,10,15]

Therefore when you pass a function as a parameter, it is called a Callback function.

Here multiplyFive and addingFive is called the Callback function.

Why the term ‘Callback’? Because it is not immediately invoked or it is invoked inside another function.

A function that invokes another function inside it must be of higher order, right, than the callback function, right?

Here arrFunc is Higher Order Function because it takes a callback(another function as a parameter).

arrFunc invokes callback functions — multiplyFive and addingFive inside it.

output.push(callBackFn(inputArray[i])); // Invoking the callBackFn

Callback function is called back by some higher functions.

Or we can say it is called after higher function is invoked.

A function that takes in or gives out another function is called Higher order functions.

We will see one Higher order functions that return another function later.

Originally published at https://www.pansofarjun.com on December 11, 2022.

--

--

Arjun Vaidy
Nerd For Tech

Founder of a startup. I explain things through first principles and intuitive mental models