Callbacks explained

Understanding callbacks in javascript

Joey Grisafe
3 min readJul 28, 2017

Since I’ve been teaching a code bootcamp it’s become increasingly apparent how many aspiring web developers have trouble understanding the nature of callbacks. I would say there are too eras in a new web dev’s life: BCE and CE, Before Callback Epiphany and Callback Epiphany (dumb, I know). Anyway, I would like to push you into the latter with this post.

First I want to break down a regular old function, that accepts a number as an argument and doubles it.

function double(numberToDouble) {

return numberToDouble * 2;
}const someNumber = 2;console.log(double(someNumber)); // 4console.log(double(5)); // 10

You can see here that I have defined a function, which accepts a number and returns that number multiplied by 2. I have called the function in two different ways, once by passing in a variable someNumber which has been assigned a value of 2, and another by simply passing the number literal 5. Both work exactly the same, and we know and accept this to be the case. But wtf you say, this has nothing to do with callbacks! Let me explain.

In javascript, functions can be used like any other variable.

In javascript, functions can be used like any other variable. They can be passed to other functions as arguments, and they can also be returned by functions. A callback is simply passing a function to another function, with the knowledge that the function receiving it will be calling it, and passing it any arguments that it needs. Here is an example of a very simple callback:

/*
* Executes a callback with no arguments and returns its
* returned value
*
* @param {function} callback - The callback function to be called
*/
function callbackCaller(callback) {
return callback()
}
function generateRandomNumberUnder100() {
return Math.random() * 100
}
const result = callbackCaller(generateRandomNumberUnder100)console.log(result) // a random number under 100

As you can see, the function callbackCaller is pretty boring and seemingly useless (it is). All it does is accepts another function, calls it, and returns the value that comes from the executed callback function. We pass in the function named generateRandomNumberUnder100 just like we did in the first example with a regular old number 5, but this time the variable contains a function. Now let’s look at the same example but instead using an anonymous function, which is simply a function that has been created on the fly and is never added to the current scope (the global scope in this example).

/*
* Executes a callback with no arguments and returns its
* returned value
*
* @param {function} callback - The callback function to be called
*/
function callbackCaller(callback) {
return callback()
}
const result = callbackCaller(function() {
return Math.random() * 100
})
console.log(result)

The only difference between these two previous examples, is that in the first we created a named function generateRandomNumberUnder100 and then passed it to our callbackCaller function, while in the second we just defined the random number generator function on the fly, in the argument list of callbackCaller.

Now I hope things are starting to become a bit more clear, if not please test out the examples above on repl.it until it’s completely understood. When you’re ready, please continue…

I think the part that gets people the most hung up is when a callback is passed arguments from the function that calls it. For example you may have seen this if you work with jQuery:

$.get('https://jsonplaceholder.typicode.com/posts/1')
.done(function(result) {
console.log(result); // [object]
})

Here we see that the .done() method takes a callback, and passes that callback the result argument. It’s important to note here that result could be named anything we want, even superCoolResult, it just so happens that we like to use argument names that make sense to us. But how in the hell did the .done() method know to pass in the result from the get request? This will be discussed in my next post about promises. Stay tuned! Anyway, let me break down passing a callback an argument with a more simple example:

/*
* Creates a random number under 10 and calls a callback function
* passing that random number, then returns the result
*
* @param {function} callback - The callback function to be called
*/
function passRandomNumberToCallback(callback) {
const randomNumber = Math.random() * 10
return callback(randomNumber)
}
// and from before
function double(numberToDouble) {
return numberToDouble * 2;
}
const result = passRandomNumberToCallback(double);console.log(result); // some random number doubled

Anyway, I hope this has made callbacks slightly more clear, if not please let me know as I’m desperately trying to figure out how to explain these pesky things. Good luck!

--

--