views:

5725

answers:

10

Like the old Albert said : "If you can't explain it to a six-year old, you really don't understand it yourself.”. Well I tried to explain JS closures to a 27 years old friend and completely failed.

Can anybody consider than I am 6 and strangely interested in that subject ?

EDIT : I have seen the scheme example given in SO, and it did not help.

+1  A: 

From my (pretty awesome) bookmarks: http://jibbering.com/faq/faq_notes/closures.html#clClose. I don't think that I could explain it any better.

Till
+37  A: 

JavaScript Closures For Dummies is the article that finally got me to understand closures. The explanation posted there is much better than anything I could write here.

Joel Anair
Brillant. I espacially love : "A closure in JavaScript is like keeping a copy of the all the local variables, just as they were when a function exited."
e-satis
though of course if the nice link goes to nirvana that answer is pretty usless :/
Florian Bösch
archive.org has it: http://web.archive.org/web/20080209105120/http://blog.morrisjohns.com/javascript_closures_for_dummies
troelskn
A good link to a clearly popular answer. The author takes the brave step of using analogies to things not entirely accurate in Javascript terms but fit the a mental model already existing in the minds many programmers such as Function calls create stake frames.
AnthonyWJones
I still don't think it's a good answer, since it depends on either the original page or the webarchive, which is either horribly slow or might not have all resources required for the page, or be gone completely.
Florian Bösch
Stackoverflow was created precisely in order NOT to have to dig trough links and mailinglists and following clues in order to arrive at the solution, please don't foobar that goal.
Florian Bösch
I must say I agree. I validated this anwser because it really gave me what I needed, but I will cancel that. Thanks (A LOT), but we should give value to people writting the anwser themself.
e-satis
Moved to new location on his site: http://blog.morrisjohns.com/javascript_closures_for_dummies.html
Dan Esparza
@Dan Thanks, link updated.
alex
+8  A: 

A closure is much like an object. It gets instantiated whenever you call a function.

The scope of a closure in javascript is lexical, which means that everything that is contained within the function the closure belongs to, has access to any variable that is in it.

A variable is contained in the closure if you

  1. assign it with var foo=1; or
  2. just write var foo;

If an inner function (a function contained inside another function) accesses such a variable without defining it in its own scope with var, it modifies the content of the variable in the outer closure.

A closure outlives the runtime of the function that spawned it. If other functions make it out of the closure/scope in which they are defined (for instance as return values), those will continue to reference that closure.

Example

function example(closure){
    // define somevariable to live in the closure of example
    var somevariable='unchanged';

    return {
        change_to:function(value){
            somevariable = value;
        },
        log:function(value){
            console.log('somevariable of closure %s is: %s',
                closure, somevariable);
        }
    }
}

closure_one = example('one');
closure_two = example('two');

closure_one.log();
closure_two.log();
closure_one.change_to('some new value');
closure_one.log();
closure_two.log();

Output

somevariable of closure one is: unchanged
somevariable of closure two is: unchanged
somevariable of closure one is: some new value
somevariable of closure two is: unchanged
Florian Bösch
+12  A: 

Closures are hard to explain because they are used to make some behaviour work that everybody intuitively expects to work anyway. I find the best way to explain them (and the way that I learned what they do) is to imagine the situation without them:

var bind = function(x) {
    return function(y) { return x + y; };
}

var plus5 = bind(5);
alert(plus5(3));

What would happen here if JavaScript didn't know closures? Just replace the call in the last line by its method body (which is basically what function calls do) and you get:

alert(x + 3);

Now, where's the definition of x? We didn't define it in the current scope. The only solution is to let plus5 carry its scope (or rather, its parent's scope) around. This way, x is well-defined and it is bound to the value 5.

Konrad Rudolph
What is being described here is currying. Its great, its functional but its entirely opaque to the target 6 year old.
AnthonyWJones
It's true that I've used currying as an example but that's not the point here and entirely irrelevant to the explanation.
Konrad Rudolph
I agree. Giving the functions meaningful names instead of the traditional "foobar" ones also helps me a lot. Semantics counts.
Ishmael
+68  A: 

Whenever you see the function keyword within another function, the inner function has access to variables in the outer function.

function foo(x) {
  var tmp = 3;
  function bar(y) {
    alert(x + y + (++tmp));
  }
  bar(10);
}
foo(2)

This will always alert 16, because bar can access the x which was defined as an argument to foo, and it can also access tmp from foo.

That is not a closure. A closure is when you return the inner function. The inner function will close-over the variables of foo before leaving.

function foo(x) {
  var tmp = 3;
  return function (y) {
    alert(x + y + (++tmp));
  }
}
var bar = foo(2); // bar is now a closure.
bar(10);

The above function will also alert 16, because bar can still refer to x and tmp, even though it is no longer directly inside the scope.

However, since tmp is still hanging around inside bar's closure, it is also being incremented. It will be incremented each time you call bar.

(Not for your 6 year old: It is possible to create more than one closure function, either by returning a list of them or by setting them to global variables. All of these will refer to the same x and the same tmp, they don't make their own copies.)

Edit: And now to explain the part that isn't obvious.

Here the number x is a literal number. As with other literals in JavaScript, when foo is called, the number x is copied into foo as its argument x.

On the other hand, JavaScript always uses references when dealing with Objects. If say, you called foo with an Object, the closure it returns will reference that original Object!

function foo(x) {
  var tmp = 3;
  return function (y) {
    alert(x + y + tmp);
    x.memb = x.memb ? x.memb + 1 : 1;
    alert(x.memb);
  }
}
var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);

As expected, each call to bar(10) will increment x.memb. What might not be expected, is that x is simply referring to the same object as the age variable! After a couple of calls to bar, age.memb will be 2!

This is the basis for memory leaks with HTML objects, but that's a little beyond the scope of this, ahem, article, ahem. http://stackoverflow.com/questions/111102#112265

Ali
you are so f####in insane. thanks for explanation. I watched douglas crockford on youtube like 3 times now and its starting to click
This example doesn't use return keyword and yet creates closure: function closureExample(obj, text, timedelay) {setTimeout(function() {document.getElementById(objID).innerHTML = text;}, timedelay);}closureExample(‘myDiv’, ‘Closure is created’, 500);
JohnMerlino
A: 

A closure is where an inner function has access to variables in it's outer function. That's probably the simplest one-line explanation you can get for closures.

Rakesh Pai
That's only half the explanation. The important thing to note about closures is that if the inner function is still being referred to after the outer function has exited, the old values of the outer function are still available to the inner one.
pcorcoran
+2  A: 

To follow up on Ali's post, refer to Leak Free Javascript Closures for more information on memory leaks related to closures.

Javascript closures can be a powerful programming technique. Unfortunately in Internet Explorer they are a common source of memory leaks. Therefore I propose a method to create closures that don't leak memory.

Rahul
+2  A: 

This is an attempt to clear up several (possible) misunderstandings about closures that appear in some of the other answers.

  • A closure is not only created when you return an inner function. In fact, the enclosing function does not need to return at all. You might instead assign your inner function to a variable in an outer scope, or pass it as an argument to another function where it could be used immediately. Therefore, the closure of the enclosing function probably already exists at the time that enclosing function was called since any inner function has access to it as soon as it is called.
  • A closure does not reference a copy of the old values of variables in its scope. The variables themselves are part of the closure, and so the value seen by accessing one of those variables is the latest value at the time it is accessed. This is why inner functions inside of loops can be tricky, since they all access the same outer variables.
  • The "variables" in a closure include named functions declared (at the top level) within the function. It also includes function arguments. The closure also has access to its containing closure's variables, all the way up to the global scope.
  • Closures use memory, but they don't cause memory leaks since JavaScript itself cleans up circular structures that have no references. IE memory leaks involving closures are caused by not disconnecting DOM attribute values that reference closures, thus maintaining references to possibly circular structures.
dlaliberte
+2  A: 

example for the first point by dlaliberte

A closure is not only created when you return an inner function. In fact, the enclosing function does not need to return at all. You might instead assign your inner function to a variable in an outer scope, or pass it as an argument to another function where it could be used immediately. Therefore, the closure of the enclosing function probably already exists at the time that enclosing function was called since any inner function has access to it as soon as it is called.

var i; 
function foo(x) {   
  var tmp = 3;   
  i = function (y) {
        alert(x + y + (++tmp)); 
  }
 } 
 foo(2);
 i(3);
someisaac
FYI: running the above shows=> 9
JJ Rohrer
+1  A: 

Can you explain closures to a 5 year old?*

I still think Google's explanation works very well and is concise:

/*
* When a function is defined in another function and it
*    has access to the outer function's context even after
*    the outer function returns
* An important concept to learn in Javascript
*/

function outerFunction(someNum) {
  var someString = 'Hai!';
  var content = document.getElementById('content');
  function innerFunction() {
    content.innerHTML = someNum + ': ' + someString;
    content = null; // IE memory leak for DOM reference
  }
  innerFunction();
}

*A C# question

Chris S