简体   繁体   中英

Javascript: how nested functions get variables from parent function

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.

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" .

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.

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.

那不是闭包,它只是对函数的两次调用,当它为true时,它将添加事件侦听器,以便打印“ aaa”,但是第二次不添加事件,因为它在添加之前返回。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM