Callbacks offer a way to extend the functionality of a function (or method) without changing its code. This approach is often used in modules (libraries / plugins), the code of which is not supposed to be changed.
Suppose we have written the following function, calculating the sum of a given array of values:
function foo(array) {
var sum = 0;
for (var i = 0; i < array.length; i++) {
sum += array[i];
}
return sum;
}
Now suppose that we want to do something with each value of the array, e.g. display it using alert()
. We could make the appropriate changes in the code of foo
, like this:
function foo(array) {
var sum = 0;
for (var i = 0; i < array.length; i++) {
alert(array[i]);
sum += array[i];
}
return sum;
}
But what if we decide to use console.log
instead of alert()
? Obviously changing the code of foo
, whenever we decide to do something else with each value, is not a good idea. It is much better to have the option to change our mind without changing the code of foo
. That's exactly the use case for callbacks. We only have to slightly change foo
's signature and body:
function foo(array, callback) {
var sum = 0;
for (var i = 0; i < array.length; i++) {
callback(array[i]);
sum += array[i];
}
return sum;
}
And now we are able to change the behaviour of foo
just by changing its parameters:
var array = [];
foo(array, alert);
foo(array, function (x) {
console.log(x);
});
In jQuery, the $.getJSON()
method to fetch JSON data is asynchronous. Therefore, passing code in a callback makes sure that the code is called after the JSON is fetched.
$.getJSON()
syntax:
$.getJSON( url, dataObject, successCallback );
Example of $.getJSON()
code:
$.getJSON("foo.json", {}, function(data) {
// data handling code
});
The following would not work, because the data-handling code would likely be called before the data is actually received, because the $.getJSON
function takes an unspecified length of time and does not hold up the call stack as it waits for the JSON.
$.getJSON("foo.json", {});
// data handling code
Another example of an asynchronous function is jQuery's animate()
function. Because it takes a specified time to run the animation, sometimes it is desirable to run some code directly following the animation.
.animate()
syntax:
jQueryElement.animate( properties, duration, callback );
For example, to create a fading-out animation after which the element completely disappears, the following code can be run. Note the use of the callback.
elem.animate( { opacity: 0 }, 5000, function() {
elem.hide();
} );
This allows the element to be hidden right after the function has finished execution. This differs from:
elem.animate( { opacity: 0 }, 5000 );
elem.hide();
because the latter does not wait for animate()
(an asynchronous function) to complete, and therefore the element is hidden right away, producing an undesirable effect.