views:

224

answers:

8

I'm trying my hardest to wrap my head around JavaScript closures.

I get that by returning an inner function, it will have access to any variable defined in its immediate parent.

Where would this be useful to me? Perhaps I haven't quite got my head around it yet. Most of the examples I have seen online don't provide any real world code, just vague examples.

Can someone show me a real world use of a closure?

Is this one, for example?

var warnUser = function (msg) {

    var calledCount = 0;
    return function() {
       calledCount++;
       alert(msg + '\nYou have been warned ' + calledCount + ' times.');

    };

};

var warnForTamper = warnUser('You can not tamper with our HTML.');

warnForTamper();
warnForTamper();

Thanks

+6  A: 

I've used closures to do things like:

a = (function () {
    var privatefunction = function () {
        alert('hello');
    }

    return {
        publicfunction : function () {
            privatefunction();
        }
    }
})();

As you can see there, 'a' is now an object with a method publicfunction (a.publicfunction()) which calls privatefunction, which only exists inside the closure, you cannot call privatefunction directly, just publicfunction().

Its a minimal example but maybe you can see uses to it? We used this to enforce public/private methods.

Francisco Soto
Ah, if this is a closure, then I have used closures without knowing it! I often put functions inside another like that, and then expose any I need public by returning an object literal like in your example.
alex
Yes, as you see, you keep the context of the function because the object you return references variables (and functions) inside it. So you've been using them, you just didn't know it.
Francisco Soto
Technically every function you make in Javascript on a browser is a closure because the window object is bound to it.
Adam Gent
+1  A: 

Yes, that is a good example of a useful closure. The call to warnUser creates the calledCount variable in its scope and returns an anonymous function which is stored in the warnForTamper variable. Because there is still a closure making use of the calledCount variable, it isn't deleted upon the function's exit, so each call to the warnForTamper() will increase the scoped variable and alert the value.

The most common issue I see on StackOverflow is where someone wants to "delay" use of a variable that is increased upon each loop, but because the variable is scoped then each reference to the variable would be after the loop has ended, resulting in the end state of the variable:

for (var i = 0; i < someVar.length; i++)
    window.setTimeout(function () { 
        alert("Value of i was "+i+" when this timer was set" )
    }, 10000);

This would result in every alert showing the same value of i, the value it was increased to when the loop ended. The solution is to create a new closure, a separate scope for the variable. This can be done using an instantly executed anonymous function, which receives the variable and stores its state as an argument:

for (var i = 0; i < someVar.length; i++)
    (function (i) {
        window.setTimeout(function () { 
            alert("Value of i was "+i+" when this timer was set" )
        }, 10000);
    })(i); 
Andy E
Interesting -1, I guess this is not "a practical use for a closure in javascript"?
Andy E
I found some use in reading it so I awarded a +1 before the downvote.
alex
@alex: thanks, I did notice the upvote. I've almost gotten used to anonymous downvotes here at SO. It only annoys me because I'd really like to know if I've said something inaccurate or wrong, and they tend to make you think you've just been downvoted by some other answerer who wants better visibility for their own answer. Fortunately, I'm not the vengeful type ;-)
Andy E
@Any E's head Well if anyone can let Andy or I know if there is any misleading information, we can amend and make SO a better place :)
alex
+4  A: 

The example you give is an excellent one. Closures are an abstraction mechanism that allow you to separate concerns very cleanly. Your example is a case of separating instrumentation (counting calls) from semantics (an error-reporting API). Other uses include:

  1. Passing parameterised behaviour into an algorithm (classic higher-order programming):

    function proximity_sort(midpoint) {
        a.sort(function(a, b) { a -= midpoint; b -= midpoint; return a*a < b*b; });
    }
    
  2. Simulating object oriented programming:

    function counter() {
        a = 0;
        return {
            inc: function() { ++a; },
            dec: function() { --a; },
            get: function() { return a; }
            reset: function() { a = 0; }
        }
    }
    
  3. Implementing exotic flow control, such as jQuery's Event handling and AJAX APIs.

Marcelo Cantos
+1  A: 

In the JavaScript (or any ECMAScript) language, in particular, closures are useful in hiding the implementation of functionality while still revealing the interface.

For example, imagine you are writing a class of date utility methods and you want to allow users to lookup weekday names by index but you don't want them to see the array of names you use under the hood.

var dateUtil = {
  weekdayShort: (function() {
    var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    return function(x) {
      if ((x != parseInt(x)) || (x < 1) || (x > 7)) {
        throw new Error("invalid weekday number");
      }
      return days[x - 1];
    };
  }())
};

Note that the days array could simply be stored as a property of the dateUtil object but then it would be visible to users of the script and they could even change it if they wanted, without even needing your source code. However, since it's enclosed by the anonymous function which returns the date lookup function it is only accessible by the lookup function so it is now tamper-proof.

maerics
A: 

I wrote an article a while back about how closures can be used to simplify event-handling code. It compares ASP.NET event handling to client-side jQuery.

http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/

stusmith
+1  A: 

If you're comfortable with the concept of instantiating a class in the object-oriented sense (i.e. to create an object of that class) then you're close to understanding closures.

Think of it this way: when you instantiate two Person objects you know that the class member variable "Name" is not shared between instances; each object has its own 'copy'. Similarly, when you create a closure, the free variable ('calledCount' in your example above) is bound to the 'instance' of the function.

I think your conceptual leap is slightly hampered by the fact that every function/closure returned by the warnUser function (aside: that's a higher-order function) closure binds 'calledCount' with the same initial value (0), whereas often when creating closures it is more useful to pass different initializers into the higher-order function, much like passing different values to the constructor of a class.

So, suppose when 'calledCount' reaches a certain value you want to end the user's session; you might want different values for that depending on whether the request comes in from the local network or the big bad internet (yes, it's a contrived example). To achieve this, you could pass different initial values for calledCount into warnUser (i.e. -3, or 0?).

Part of the problem with the literature is the nomenclature used to describe them ("lexical scope", "free variables"). Don't let it fool you, closures are more simple than would appear... prima facie ;-)

EdwardGarson
A: 

There is a section on Practical Closures at the Mozilla Developer Network.

alex
+2  A: 

Another common use for closures is to bind this in a method to a specific object, allowing it to be called elsewhere (such as as an event handler).

function bind(obj, method) {
    if (typeof method == 'string') {
        method = obj[method];
    }
    return function () {
        method.apply(obj, arguments);
    }
}
...
document.body.addEventListener('mousemove', bind(watcher, 'follow'), true);

Whenever a mousemove event fires, watcher.follow(evt) is called.

Closures are also an essential part of higher-order functions, allowing the very common pattern of rewriting multiple similar functions as a single higher order function by parameterizing the dissimilar portions. As an abstract example,

foo_a = function (...) {A a B}
foo_b = function (...) {A b B}
foo_c = function (...) {A c B}

becomes

fooer = function (x) {
    return function (...) {A x B}
}

where A and B aren't syntactical units but source code strings (not string literals).

See "Streamlining my javascript with a function" for a concrete example.

outis
Thanks for stopping by with a good answer +1
alex