Callbacks in JavaScript: Why They Exist
Understanding how JavaScript handles tasks step by step
Introduction
When I first started learning JavaScript, one thing felt strange - functions behaving like values.
You can store then in variables, pass them around and even return them from other functions. This idea is the foundation of callbacks and once it clicks, a lot of JavaScript concepts start making sense.
Functions as Values in JavaScript
In JavaScript, functions are treated like any other value. That means you can do things like,
function greet () {
console.log("Hello");
}
function execute(fn) {
fn();
}
execute(greet);
Here, greet is passed as an argument to another function to another function. This is where the concept of a callback begins.
What is a Callback Function?
A callback function is simply a function that is passed into another function and executed later.
function sayHello(name) {
console.log("Hello " + name);
}
function processUserInput(callback) {
const name = "Elon";
callback(name);
}
processUserInput(sayHello);
Here:
sayHellois the callbackprocessUserInputdecides when to call it
So the control of execution is handed over.
Passing Functions as Arguments
This pattern is used everywhere in JavaScript
function calculate(a, b, operation) {
return operation(a, b);
}
function add(x, y) {
return x + y;
}
console.log(calculate(2, 3, add))
Instead of hardcoding logic, we pass behavior as a function. This makes code more flexible and reusable.
Why Callbacks Are Used in Asynchronous Programming
JavaScript is single-threaded, which means it can do one thing at a time. But in real application, tasks like Fetching data from API, Reading files, Waiting for user actions, take time.
Callbacks help handle these situations without blocking the main thread.
Example:
console.log("Start");
setTimeout(() =>{
console.log("This runs later");
},2000);
console.log("End");
Output:
Start
End
This runs later
The function inside
setTimeoutis a callbackIt runs after 2 seconds, without stopping the rest of the code
Common Callback Usage Scenarios
Event Handling
button.addEventListener("click", () => {
console.log("Button clicked");
});
The function runs only when the event happens.
Array Methods
const numbers = [1, 2, 3];
numbers.forEach((num) => {
console.log(num);
});
Here the function passed to forEach is a callback.
Timers
setInterval(() => {
console.log("Running every second");
}, 1000);
Again, a callback controls repeated execution.
The Problem with Callback Nesting
setTimeout(() => {
console.log("Step 1");
setTimeout(() => {
console.log("Step 2");
setTimeout(() => {
console.log("Step 3");
}, 1000);
}, 1000);
}, 1000);
A Better Way Exists (But Why Learn Callbacks?)
Today we have:
Promises
Async/Await
But callbacks are still important because:
They are the foundation of async JavaScript
Many APIs still use them
Understanding them helps you understand the event loop better
Important Points
Callbacks exist because JavaScript needed a way to handle tasks that don't finish immediately. Instead of waiting and blocking everything, JavaScript says,
“Give me a function, and I’ll call it when the work is done.”
That simple idea powers:
Events
Timers
Async operations
Once we understand callbacks, we’re not just writing JavaScript — we’re understanding how it thinks.