Callbacks: Functions as Arguments

JavaScript ES2024 · ✓ verified by execution on 2026-08-15

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. They form the foundation of asynchronous programming and higher-order functions in JavaScript.

In many other programming languages, functions are rigid structures that only exist to be called directly. But because functions in JavaScript are first-class objects, they behave exactly like strings, numbers, or arrays. You can store a function in a variable, return a function from another function, or—most commonly—pass a function as an argument into another function. The receiving function can then choose exactly when and how to execute it. This delayed execution gives JavaScript its incredible flexibility, allowing it to handle everything from user clicks to network requests without freezing the browser.

My Callback function logHi() { console.log('Hi'); } Higher-Order Function function execute(cb) { cb(); // executed here } passed as argument
A callback function is passed as a value into a higher-order function, which executes it later.

Synchronous Callbacks

Callbacks can be executed synchronously (immediately) or asynchronously (later). Array methods like forEach, map, and filter use synchronous callbacks. This means they block the main execution thread until every iteration is entirely complete. While this is fast and predictable for simple arrays, you should never put heavy, slow computations inside a synchronous callback, or you risk freezing the user interface entirely.

javascript · visualize
function invoke(cb) {
  console.log('Before');
  cb();
  console.log('After');
}
invoke(() => console.log('During'));
Before
During
After

Notice the order of execution. The invoke function executes the callback before it finishes.

The Execution Trap (Parentheses)

The most common and devastating mistake beginners make with callbacks is accidentally executing the function right when they meant to pass it as a reference. This usually happens because we are so accustomed to typing parentheses after a function name.

When passing a function as a callback, you must pass the function reference without parentheses. Including parentheses executes the function immediately and passes its return value instead.

Predict the output javascript

Read the code. What exactly will it print? Commit to an answer before you look.

function sayHi() {
  console.log('Hi');
  return 'Returned!';
}

function execute(cb) {
  console.log('Executing...');
  try {
    cb();
  } catch(e) {
    console.log(e.name);
  }
}

// What happens here?
execute(sayHi());
Output
Hi
Executing...
TypeError

Because sayHi() has parentheses, it executes immediately. It logs Hi and returns the string 'Returned!'. Then, execute tries to run 'Returned!'(), which results in a TypeError because a string is not a function.

Higher-Order Functions

The function that accepts other functions as arguments (or returns them) is called a higher-order function.

javascript · visualize
function generateMultiplier(factor) {
  return function(n) { return n * factor; };
}
const doubler = generateMultiplier(2);
console.log(doubler(5));
10

Inline and Arrow Functions

You don’t have to define a function separately before passing it as a callback. You can define functions inline anonymously right where you pass them, which is often preferred for single-use logic.

javascript · visualize
const numbers = [1, 2, 3];
numbers.forEach(n => console.log(n * 2));
2
4
6

Check yourself

What happens when you pass `myFunc()` instead of `myFunc` as a callback?

Reveal answer

It executes immediately and its return value is passed. — `myFunc()` immediately executes the function and passes its return value. `myFunc` passes the function itself to be executed later.

Are all callbacks executed asynchronously in JavaScript?

Reveal answer

No, callbacks can be synchronous, like in Array.prototype.map. — Callbacks can be synchronous. Array methods like `forEach`, `map`, and `filter` execute their callbacks immediately and synchronously.

What is a higher-order function?

Reveal answer

A function that accepts other functions as arguments or returns a function. — A higher-order function is one that operates on other functions, either by taking them as arguments or by returning them.

Challenges

Challenge 1 +20 XP

Write a higher-order function `calculate` that accepts two numbers and a callback function. It should execute the callback with the two numbers and return the result.

javascript
  • Test 1 — expects "8"
Need a hint? (−25% XP)

You need to invoke the `operation` parameter, passing `a` and `b` as arguments.

Show solution (0 XP)
function calculate(a, b, operation) {
  return operation(a, b);
}

console.log(calculate(5, 3, function(x, y) { return x + y; }));

🐞 Bug Hunt +30 XP

This filter function is supposed to return an array of strings that pass the test function, but it's broken. Fix the code so it properly invokes the callback.

This code runs. It just does the wrong thing. Read it, find the defect, fix it — the tests below decide when you are right.

javascript
  • Test 1 — expects "[ 'Alice', 'Charlie' ]"
Need a hint? (−25% XP)

`testFunc` is a function, not a boolean. You need to call it with the current name `names[i]` to get the boolean result.

Show solution (0 XP)
function filterNames(names, testFunc) {
  const result = [];
  for(let i = 0; i < names.length; i++) {
    if(testFunc(names[i])) {
      result.push(names[i]);
    }
  }
  return result;
}

console.log(filterNames(['Alice', 'Bob', 'Charlie'], name => name.length > 3));