Callbacks and Higher-Order Functions in JavaScript
Introduction
A callback is a function passed into another function to run later—on clicks, timers, or when data arrives. A higher-order function takes or returns functions. You already used these with map and addEventListener; this chapter ties the pattern together for async-style APIs.
Prerequisites
Callback Basics
javascript
// greet calls fn after building message
function greet(name, callback) {
const message = `Hello, ${name}`;
callback(message);
}
greet("Ada", (msg) => console.log(msg));Higher-Order Function
javascript
// repeat runs action n times
function repeat(n, action) {
for (let i = 0; i < n; i++) {
action(i);
}
}
repeat(3, (i) => console.log(`step ${i}`));Array Methods as HOFs
map, filter, forEach are built-in higher-order functions:
javascript
const ids = [1, 2, 3].map((id) => `user-${id}`);
console.log(ids);Timing Callbacks
javascript
// setTimeout schedules callback
setTimeout(() => {
console.log("2 seconds later");
}, 2000);In Node, timers need the process to stay alive or use clearTimeout in tests.
Error-First Callback Style (Node Tradition)
javascript
// (err, data) pattern — still seen in older APIs
function fakeRead(path, callback) {
if (!path) return callback(new Error("missing path"));
callback(null, `contents of ${path}`);
}
fakeRead("/tmp/demo.txt", (err, data) => {
if (err) return console.error(err.message);
console.log(data);
});Modern code often prefers Promises—covered in later async chapters.
Returning Functions from HOFs
javascript
// compose two unary functions
function compose(f, g) {
return (x) => f(g(x));
}
const add1 = (n) => n + 1;
const double = (n) => n * 2;
const add1ThenDouble = compose(double, add1);
console.log(add1ThenDouble(3));Mini Example: once Callback Wrapper
javascript
// Run callback only first time
function once(fn) {
let called = false;
return (...args) => {
if (called) return;
called = true;
return fn(...args);
};
}
const init = once(() => console.log("init once"));
init();
init();FAQ
Callback hell?
Deep nesting hurts readability—use named functions, Promises, or async/await.
Is every function passed a callback?
Loosely yes—in precise terms, callbacks are invoked by the callee you pass them to.
Sync vs async callbacks?
Sync runs immediately; async runs later—know which to avoid race bugs.