0

Javascript supports First Class Functions, in which case we can pass the function as an argument. An anonymous function that is defined inside an argument list of another function, what is the lexical environment (i.e scope) of that anonymous function?

for example:

var m = 2;

(function(p1,p2){
   p2(p1);
})(true, function(p1){  // an anonymous function passed as an argument.
   m = 3;
   if(p1){...}
}); // the end of self-invoked function expression.
Profess Physics
  • 317
  • 4
  • 11
  • probably it's `{p1: true, m: 3}` ? – devellopah May 31 '17 at 23:01
  • The function would have access to the scope where it was defined and include any parent scope (e.g. global/window). If defined inside of another function, it would have access to any variables defined within that function. If passed in as an argument like a callback, it wouldn't have access to variables defined within the function it was passed into because it was defined outside that function and passed in as an argument. – Jonathan Kuhn May 31 '17 at 23:02
  • IslamI bakaev sorry did not get it. Jonathan Kuhn So the question is.., shall I consider the anonymous function defined in the argument list as a function defined inside another function ? – Profess Physics May 31 '17 at 23:11
  • 1
    In your example, the argument function would not have access to the p1 or p2 variable as defined in the first function because you are defining the argument outside of that function. It's scope would be window/global (if this was not within another function). The argument function does however have it's own definition of p1 and so it gets a copy of the p1 as an argument from the parent function. Variable `m` is part of the parent scope of both and so would be accessible to either function. – Jonathan Kuhn May 31 '17 at 23:12
  • 2
    To answer your question, no. The argument function is defined first outside of the other function and the result from that is passed in. To see this, if you defined a variable within the first function, the argument function would not have access to that variable, even if invoked after that definition. – Jonathan Kuhn May 31 '17 at 23:13
  • I see. thank u for helping me out. I did test it.., that's true. – Profess Physics May 31 '17 at 23:19

3 Answers3

2

The function would have access to the scope where it was defined and include any parent scope (e.g. global/window). If defined inside of another function, it would have access to any variables defined within that function. If passed in as an argument like a callback, it wouldn't have access to variables defined within the function it was passed into because it was defined outside that function and passed in as an argument.

Example:

var a = 1;

(function(callback){ //func1
    //access variable in parent scope
    console.log('func1', a); //outputs 1

    //define a new variable within this function's scope
    var b = 2;

    //call our callback
    callback();

    //define and call a function within this function's scope
    (function(){ //func3
        //access variable in parent scope
        console.log('func3', a); //outputs 1
        //access variable in parent function scope
        console.log('func3', b); //outputs 2
    })();

})(function(){ //func2
    //access variable in parent scope
    console.log('func2', a); //outputs 1
    //access variable from invoking function
    console.log('func2', b); //outputs undefined
});

This would output something like:

func1 1
func2 1
func2 undefined
func3 1
func3 2

Where all the functions can see variable a because it is in a parent scope to all functions. The argument function can't see variable b because b is defined in another function and the argument function was defined outside and passed in as an argument. And the function defined within the first function can see both a and b.

Jonathan Kuhn
  • 15,279
  • 3
  • 32
  • 43
1

Calling an IIFE is effectively the same as first assigning the function to a variable, then then calling the function through that variable; as with any other use of anonymous functions, it's just a shortcut that avoids giving a name to the function. So:

(function(p1,p2){
   p2(p1);
})(true, function(p1){  // an anonymous function passed as an argument.
   m = 3;
   if(p1){...}
});

is equivalent to:

var temp = function(p1,p2){
   p2(p1);
};
temp(true, function(p1) {
   m = 3;
   if(p1){...}
});

except for the addition of temp to the outer scope; since this variable doesn't appear anywhere else, it has no effect. The scopes of all other variables are identical in the two scenarios.

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

When you're unsure what the scopes of a function defined in the arguments list of a call is, notice that

fn(function x(…) { … })

is equivalent to

_temp = function x(…) { … };
fn(_temp)

Arguments are evaluated before the actual call, and they're evaluated in the same scope as the call itself is evaluated in.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375