Functions can be passed around just like any value in JavaScript.

Callback Functions

A callback function is a function passed into another function as an argument. The function that receives the callback function is often referred to as the “parent” function. The parent function will, at some point in the future, execute or call the callback.

For example, the add function below accepts a function as its third argument (via the parameter callback). When add is invoked, the function passed to it logs the sum of the values passed in for a and b.

function add(a, b, callback) {
  callback(a + b);
}

add(2, 4, function(sum) {
  console.log(sum); // 6
});

In the following example, the function getUserName accepts a function as an argument (via the parameter callback). The greeting function passed to getUserName is invoked after prompt() captures a name and stores it in the variable name.

function getUserName(callback) {
  const name = prompt('What is your name?');
  callback(name);
}

function greeting(name) {
  alert('Hello, ' + name);
}

getUserName(greeting); // a reference to the greeting function is passed to the function

DOM Events

Callbacks are used in both synchronous and asynchronous functions, so you might already be familiar with the concept of callbacks. For example, you use callbacks every time you listen for DOM events. The callback passed to addEventListener is an arrow function that runs JavaScript only when the user clicks a button:

btn.addEventListener('click', () => {
  // Perform some action on click inside this callback
  console.log('I was clicked!');
});

Iteration methods

Array iteration methods like map()filter(), and forEach() accept a callback function that processes each item in the original array. For example, convert each item in the fruits array to uppercase:

const capitalizedFruits = fruits.map( fruit => fruit.toUpperCase() );

Return a new array containing only those items in the sNames array that begin with the letter ‘S’:

const sNames = names.filter( name => {
  return name.charAt(0) === 'S';
});

Console log each item in the fruits array:

fruits.forEach( fruit => console.log(fruit) );

Continuation-passing style (CPS)

With callbacks, you can also create a chain of function calls (or a sequence of tasks) where one task runs after another is completed. This is referred to as continuation-passing style (CPS).

For example, each function takes a callback (or continuation function) as its last argument:

function add(x, y, callback) {
  callback(x + y)
}
function subtract(x, y, callback) {
  callback(x - y);
}
function multiply(x, y, callback) {
  callback(x * y);
}
function calculate(x, callback) {
  callback(x);
}

calculate(5, (n) => {
  add(n, 10, (n) => {
    subtract(n, 2, (n) => {
      multiply(n, 5, (n) => {
        console.log(n); // 65
      });
    });
  });
});

The functions get invoked and processed in a sequence. As you’ll soon learn, this style of code can lead to what’s referred to as “callback hell” or the “pyramid of doom”, which can make your program difficult to follow and maintain.