Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scope of anonymous function passed as function argument

Given the following code, what should I expect to see in the alert?

var a = 100;
function afunc(infunc){
  a = 10;
  infunc.call();
}

afunc(function(){alert(a)});

My initial thought was that my browser should alert 100 since the variable a=100 would be in scope for the anonymous function passed as an argument to afunc. But this assumes that the anonymous function is actually defined in the global context. Apparently that's not the case as the browser alerts 10. So why is a=10 ahead of a=100 in the scope chain?

Thanks!

like image 583
Al R. Avatar asked Jul 20 '12 16:07

Al R.


3 Answers

Because you're setting a to 10 before you call the anonymous function. a is in fact global, but you're setting it to 10.

like image 55
Rick Mangi Avatar answered Oct 23 '22 16:10

Rick Mangi


So why is a=10 ahead of a=100 in the scope chain?

It's not. You've only defined 1 a variable, which is simply being changed from 100 to 10 before being alerted.

If you want the as to be distinct variables with their own values, they both need a var keyword:

var a = 100
function afunc(infunc){
  var a = 10;
  infunc.call();
}

afunc(function(){alert(a)})​
like image 25
Jonathan Lonowski Avatar answered Oct 23 '22 14:10

Jonathan Lonowski


Consider the following example:

var a = 100;

function afunc(infunc){
  a = 10;
  var f = function (){
    console.log(a);
  };
  f.call();
  infunc.call();
}

afunc(function (){ console.log(a); });

We assign a value of 10 to a within the scope of afunc, and then call two functions one after the other that simply log the value of a. In this case, you would expect both functions to log 10 as the value of a, and that's in fact what happens.

In your example, infunc will be executed in essentially the same scope as any local function defined in afunc, regardless of where it was actually defined. Since you assigned a value to a in a narrower scope, that's the value of a when you call infunc.

Functions do retain some scope from their definition, as in the following example:

function bfunc(){
  var b = 'hello';
  return function (){ console.log(b); };
}

afunc(bfunc());

Here, the anonymous function returned by bfunc is actually called from within the scope of afunc, but it's still able to log the correct value of b as it was assigned in the original scope. If you were to change afunc to assign a different value to b, it would still log "hello" because the b defined in afunc is a different variable than the b defined in bfunc.

like image 44
Brandan Avatar answered Oct 23 '22 15:10

Brandan