There are many uses for callbacks in JavaScript. But the one I really like—and not often talked about—is modifying the behavior of some internal parts of that function.
Let me show you an example.
Example
Let’s say you have a function that fetches and returns some post data.
function getPostById(id) {
// I'm going to return a literal object here,
// but imagine it's fetching the post from somewhere
return {
title: 'Post Title',
date: new Date().toString(),
tags: ['tag1', 'tag2']
}
}
I’m going to focus on the date field for this example.
The date returned here is formatted using the toString
method. If I want to change it to a different format, I have to parse that string into a date object, and then format it however I want.
But wouldn’t it be nice if I can specify the formatting code directly in the function without modifying the function code?
A great thing about JavaScript is that it has first-class functions. This means I can pass functions as values to another functions—we call them callbacks.
So, I can modify the function above to move the formatting code into a callback instead of hardcoding it in the body of the function.
function getPostById(id, fnDateFormatter = (date) => date.toString()) {
return {
title: 'Post Title',
date: fnDateFormatter(new Date()),
tags: ['tag1', 'tag2']
}
}
If you run the code above, it will work exactly as the previous one. The difference here is that I format new Date()
using the fnDateFormatter
callback. Also note how I can specify a default callback in the parameters directly—isn’t JavaScript great?
Because fnDateFormatter
is a parameter that accepts a function as a value, I can pass it any other function I want when calling it.
function myDateFormatter(date) {
return date.toLocaleDateString('en-us', {
weekday: 'long',
year: 'numeric',
month: 'short',
day: 'numeric'
})
}
const testPostWithDefaultFormatter = getPostById(1)
const testPostWithMyFormatter = getPostById(1, myDateFormatter)
I called the function twice: one with the default formatter, and one with a custom formatter. Note how I didn’t need to touch the original function code in either one.