0

I've read everything about js closures but can't understand the following code:

function main(condition){
  var a;
  if (condition){
    a="aaa";
  }
  else 
  {
    a="bbb";
    return;
  }
  button.addEventListener("click", function(){ alert(a);});
}
main(true);
main(false);

After that click button. The result is:"aaa". Doest this mean that for nested function doesn't keep the reference to variables but copy them? Please explain.

2
  • what is button? where is that defined? Commented Dec 10, 2014 at 7:55
  • @unikorn In global context. But is it so important? Commented Dec 10, 2014 at 7:57

4 Answers 4

3

The first time you run main, you assign "aaa" to a (which is a local variable) and then bind an event handler which reads that variable.

The second time you run main, you assign "bbb" to a (since this is a different invocation of the function, it is a different local variable). You do not bind an event handler that reads that variable since you return first.

When the click event fires, the function it runs is in the scope of the a from the first call, not the second call, so the value is "aaa".

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your time. That's all clear. We click the button after the execution of main function (two times our case) - when all local variables are dead. The question is how does this inner function save state of a?
@PashaTurok — It was declared in the scope of that variable, so it has access to that variable. The rest is an implementation detail of the particular JS engine.
0

I would say that this is what closures are all about. Closures are "internal functions" that retain access to the values of variables that were "valid" at the moment when the internal function was created even after the "outer function" returned.

Consider the following example:

var outerFunc = function(a) {
  return function (x) {
    return x+a;
  }
} //the outer function returns a function

Now let's invoke the outer function and store the returned value in the variable newFunc:

var newFunc = outerFunc(15); //the outer function has been invoked, newFunc is a function

newFunc(1); //let's invoke the resulting "inner function"

The result will be 16. The inner function will always remember the value 15, even if you invoke the outer function with other argument values. This is how JavaScript works.

In your example with the event listener something very similar is happening. The inner function (with the alert) is registered as a reaction to the click event, and it always 'remembers' the value of a. When you press the button, this invokes this 'inner' function.

Comments

0

To get the behavior you may want, try:

var main = function () {
    var a;
    return function() {
        if (condition){
            a="aaa";
        }
        else 
        {
            a="bbb";
            return;
        }
        button.addEventListener("click", function(){ alert(a);});
    };
}();

main(true);
main(false);

This works because it defines a in a way which persists across invocations of the function, which as another answerer pointed out, is the problem.

2 Comments

Thank you for your time. I wrote that example just to ilustrate my question. I want to understand if javascript copies and keeps the values from functions above.
Yes, it does. Absolutely. That's a basic aspect of the language. However, it does not persist function variables across multiple function invocations, as you have seen.
-1

that is not a closure, its just a double call to a function, when its true it adds the event listener so that it prints 'aaa' but second time it isn't added an event, because it returns before adding it.

1 Comment

Actually, it is exactly a closure. The function passed to addEventListener "closes" on the variable a.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.