Understanding Callbacks and Higher-Order Functions in JavaScript

JavaScript is a flexible language, allowing functions to be assigned to variables, passed as arguments, and even returned from other functions. This capability is made possible because JavaScript treats functions as first-class citizens. But what does this mean, and how does it lead to concepts like callbacks and higher-order functions?

In this post, we'll explore these concepts and see them in action with some practical examples.

Functions as First-Class Citizens

In JavaScript, functions are considered first-class citizens, meaning they can:

  1. Be assigned to variables.

  2. Be passed as arguments to other functions.

  3. Be returned as values from functions.

This makes JavaScript highly flexible, laying the groundwork for advanced patterns with functions.

What is a Higher-Order Function?

A higher-order function is any function that:

  • Takes a function as an argument, and/or

  • Returns a function as a value.

Let’s see how built-in higher-order functions work in JavaScript.

Array Methods

JavaScript provides many higher-order functions through array methods, such as map, filter, forEach, and reduce. Each of these methods accepts a function as an argument and applies it to each item in an array.

For instance, forEach allows us to iterate over an array and apply a function to each element:

const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function(number) {
  console.log(number * 2);
});
// Output: 2, 4, 6, 8, 10

Here, forEach takes an anonymous function that logs each doubled number, making forEach a higher-order function.

Timer Events

JavaScript also provides higher-order functions for timing events: setTimeout and setInterval. These functions accept another function as an argument, which they execute after a specified duration:

setTimeout(function() {
  console.log("This message appears after 1 second.");
}, 1000);

In this case, setTimeout is a higher-order function that runs the callback after a 1-second delay.

Creating Your Own Higher-Order Function

Higher-order functions aren’t limited to those provided by JavaScript; we can create our own! Here’s an example of a custom higher-order function that takes a callback function to greet customers:

function greetCustomer(greetingFunc, firstName, lastName) {
  const fullName = `${firstName} ${lastName}`;
  greetingFunc(fullName);
}

greetCustomer(function(name) {
  console.log(`Hello, ${name}!`);
}, "Jane", "Doe");
// Output: Hello, Jane Doe!

Here, greetCustomer takes greetingFunc as an argument. Inside greetCustomer, the callback function greetingFunc is executed with fullName, making greetCustomer a higher-order function.

Returning a Function as a Value

We can also design higher-order functions that return other functions:

function createGreeting(salutation) {
  return function(name) {
    console.log(`${salutation}, ${name}!`);
  };
}

const greet = createGreeting("Welcome");
greet("Jane");
// Output: Welcome, Jane!

In this example, createGreeting returns a new function that includes the salutation passed to it. This returned function can then be used as a personalized greeting for any name.

Callback Functions

A callback function is simply a function passed as an argument to another function. It’s called within the higher-order function when needed.

For instance, setTimeout takes a callback function that runs after a set period:

setTimeout(function() {
  console.log("Callback in action!");
}, 2000);

Here, the anonymous function we passed as an argument is the callback function, which will log a message after 2 seconds.

The Difference Between Higher-Order Functions and Callbacks

It’s essential to understand that:

  • A higher-order function takes a function as an argument or returns a function.

  • A callback function is a function passed into another function to be executed later.

Imagine a backpack (higher-order function) holding a book (callback). The backpack carries the book and can access it when needed. Similarly, a higher-order function "carries" the callback function and calls it at the right moment.

Wrapping Up

By treating functions as first-class citizens, JavaScript enables powerful patterns like higher-order functions and callbacks. These tools help you write cleaner, reusable, and modular code.

Try experimenting with higher-order functions and callbacks in your code, as they’re commonly used in asynchronous programming, event handling, and functional programming.

10
Subscribe to my newsletter

Read articles from Stanley Owarieta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Stanley Owarieta
Stanley Owarieta

𝗔𝘀𝗽𝗶𝗿𝗶𝗻𝗴 𝗙𝗿𝗼𝗻𝘁𝗲𝗻𝗱 𝗗𝗲𝘃𝗲𝗹𝗼𝗽𝗲𝗿 passionate about 𝙅𝙖𝙫𝙖𝙎𝙘𝙧𝙞𝙥𝙩, 𝙘𝙤𝙙𝙞𝙣𝙜, 𝙖𝙣𝙙 𝙗𝙪𝙞𝙡𝙙𝙞𝙣𝙜 𝙢𝙮 𝙛𝙪𝙩𝙪𝙧𝙚 𝙞𝙣 𝙩𝙚𝙘𝙝. Along with my 𝙡𝙤𝙫𝙚 for 𝙛𝙖𝙨𝙝𝙞𝙤𝙣, 𝙜𝙖𝙢𝙞𝙣𝙜, 𝙖𝙣𝙙 𝙡𝙪𝙭𝙪𝙧𝙮 𝙡𝙞𝙫𝙞𝙣𝙜, I have big dreams like 𝙤𝙬𝙣𝙞𝙣𝙜 𝙖 𝙥𝙧𝙞𝙫𝙖𝙩𝙚 𝙟𝙚𝙩 and 𝙡𝙞𝙫𝙞𝙣𝙜 𝙞𝙣 𝙖 𝙡𝙪𝙭𝙪𝙧𝙮 𝙝𝙤𝙢𝙚 𝙤𝙣𝙚 𝙙𝙖𝙮. Since 2021, I’ve invested in 𝗔𝗽𝗽𝗹𝗲, 𝗔𝗺𝗮𝘇𝗼𝗻, 𝗦𝗵𝗼𝗽𝗶𝗳𝘆, 𝗮𝗻𝗱 𝗚𝗼𝗼𝗴𝗹𝗲—working toward financial independence. I also look forward to being a 𝗹𝗼𝘃𝗶𝗻𝗴 𝗳𝗮𝘁𝗵𝗲𝗿 𝗮𝗻𝗱 𝗮 𝗱𝗲𝘃𝗼𝘁𝗲𝗱 𝗽𝗮𝗿𝘁𝗻𝗲𝗿, growing a 𝗺𝗶𝗹𝗹𝗶𝗼𝗻-𝗱𝗼𝗹𝗹𝗮𝗿 𝗯𝗿𝗮𝗻𝗱 together with my 𝗳𝘂𝘁𝘂𝗿𝗲 𝘄𝗶𝗳𝗲. Let’s connect and inspire each other on this journey!