Search code examples
javascriptcallbackclosures

What are the use cases for closures/callback functions in JavaScript?


I was listening to Crockford's talk on JavaScript closures and am convinced of the benefit of information hiding, but I do not have a firm understanding of when to use callback functions.

It is mostly a true statement that a person could accomplish the same functionality with or without callbacks.

As someone who is writing code, what heuristics or cues should I keep in mind when determining when to use callbacks/closures?

I am not looking for the blanket statement 'Closures make more secure code', rather a list of practical examples or rules of thumb for when callbacks are the right idea.

Crockford's Presentation: http://www.yuiblog.com/blog/2010/04/08/video-crockonjs-5/


Solution

  • Firstly:

    • Callback: A function passed as an argument to another function, usually to be called as a result of an event occurring.
    • Closure: A retained scope. I.e. the concept that when you declare a function within another function, the outer function's scope is accessible within the inner function.

    Callbacks can also be closures but are not always.

    This is a callback:

    someProcess(myCallback);
    
    function myCallback() {
        alert('Done...');
    }
    
    function someProcess(callback) {
        // does stuff...
        // ...
        callback();
    }
    

    A closure:

    function foo(msg) {
    
        function bar() {
            // I can access foo's scope
            // (i.e. bar can access everything that foo can access)
            alert(msg);
        }
    
        return bar;
    
    }
    
    foo('hello')(); // alerts "hello"
    

    One common usage of closures is to provide information-hiding, which is helpful in bringing some kind of encapsulation to the language. Have a look at the module pattern to see this in action.

    Another common usage is when the binding event handlers to elements. E.g.

    var myElements = [ /* DOM Collection */ ];
    
    for (var i = 0; i < 100; ++i) {
        myElements[i].onclick = function() {
            alert( 'You clicked on: ' + i );
        };
    }
    

    That wouldn't work. By the time the element is clicked, the variable i is 99. To make this work properly we could use a closure to capture the value of i:

    function getHandler(n) {
        return function() {
            alert( 'You clicked on: ' + n );
        };
    }
    
    for (var i = 0; i < 100; ++i) {
        myElements[i].onclick = getHandler(i);
    }