A callback is a function supplied to other code so that code can invoke it at an appropriate point. JavaScript makes this possible because functions can be passed as arguments. “Later” does not necessarily mean asynchronous: an array operation might call its callback while it runs, whereas a browser event handler waits for an event. section 3.1.1 section 3.1.2
Pass the function, then call it
function run(callback) { return callback(); } function getText() { return "Hello"; } run(getText); // "Hello" Pass getText, not getText(): the first gives run a function to invoke; the second gives it the function’s result. section 3.1.2
Where callbacks earn their keep
- Register a function with addEventListener to react to a browser event, or pass a comparison function to sort to control an array’s order. section 3.1.2
- Pass a function to a long-running request so the UI need not wait for the result. The callback runs when the task finishes. section 6.3.1
- Pass success and failure callbacks to a promise’s then method to handle resolution or rejection. section 6.3
Callbacks often need information from their surroundings. A timer callback can use a closure to retain an element, a counter, and a timer reference across animation steps. Keeping those variables inside the animation function gives each animation its own state instead of making multiple animations share globals. section 5.2.2
Listing 5.4. Using a closure in a timer interval callback
<div id="box1">First Box</div> #A
<script>
function animateIt(elementId) {
var elem = document.getElementById(elementId); #B
var tick = 0; #C
var timer = setInterval(function(){ #D
if (tick < 100) { #E
elem.style.left = elem.style.top = tick + "px"; #E
tick++; #E
} #E
else {
clearInterval(timer);
assert(tick === 100, #F
"Tick accessed via a closure.");
assert(elem,
"Element also accessed via a closure.");
assert(timer,
"Timer reference also obtained via a closure." );
}
}, 10); #G
}
animateIt("box1"); #H
</script>
The timer callback updates an element through variables retained from its enclosing animation function. section 5.2.2
Watch two traps. First, a callback’s this may not be the object whose method you passed: an event callback can receive the event-raising element as its context instead. When invoking a callback yourself, call or apply can set its context explicitly. Second, try-catch around the start of an asynchronous request generally cannot catch errors arising when its callback runs in a later event-loop step. Error arguments are one convention; deeply nested, dependent callbacks can still make control flow and error handling hard to follow. Promises and generators offer an alternative for that case. section 4.2.4 section 6.3.1 section 6.4


















