1

I believed at first look both self invoking function is same only difference between them is in first one I am passing callback function and then executing by arguments object while in second doing same thing by making function self invoking. Now come to points of accessing parent variable in first one example name is "undefined" while in second one example it's accessible and giving output "Nishant" I am not able to figure out how It's working!!

(function(){
    var name = "Nishant";
    arguments[0]();

})(function(){console.log(name);});

Output: (an empty string)

(function(){
  var name = "Nishant";
  (function(){console.log(name);})()
})();

Output: Nishant

Nishant Kumar
  • 5,995
  • 19
  • 69
  • 95

2 Answers2

2

I am not able to figure out how It's working!!

JavaScript has lexical scope. That means the scope is determined by where the functions are defined inside the source code (unlike dynamic scope, where the scope is determined when the functions are called at runtime).

Lets add some names to your functions so we can reference them more easily:

(function foo(){
    var name = "Nishant";
    arguments[0]();
})(function bar(){console.log(name);});

In this case bar is defined outside of foo and hence cannot have access to the variable defined inside of foo. In fact, at the moment bar is created, the variable name inside foo doesn't even exist yet, since foo hasn't been executed yet.
Maybe it's easier to see when you do not inline the definition:

function bar(){console.log(name);}

(function foo(){
    var name = "Nishant";
    arguments[0]();
})(bar);

This might look more familiar, and I bet you wouldn't expect that name inside bar has anything to do with name inside foo, right?


In the other case,

(function foo(){
  var name = "Nishant";
  (function bar(){console.log(name);})()
})();

you defined bar inside of foo. name is also inside foo and hence bar has access to that variable (lexical scope + closure).

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Just to be sure, any comment on the claim the asker made, i quote "Callback Functions Are Closures When we pass a callback function as an argument to another function, the callback is executed at some point inside the containing function’s body just as if the callback was defined in the containing function", because he just left and didn't answer my questions. It is **not** possible for callbacks to access the scope of the function being passed to via closure? – Winchestro Jun 08 '14 at 15:25
  • Nope. That would only be possible if JS had dynamic scope, which it doesn't. – Felix Kling Jun 08 '14 at 15:33
  • Thanks. Phew now I can finally stop feeling like a total idiot. I tried everything I could to reconstruct that behavior he suggested after the asker left, but wasn't able to and thought I would miss something obvious. – Winchestro Jun 08 '14 at 15:36
1

the "name" in the first version refers the global window.name property*, and in the second example to the private var name through the closure. The window.name property is optional and defaults to an empty string.

If this property wouldn't happen to exist your first example would throw a reference error.

The closure is created at the scope a function was declared, not at the point it got called and in the first example the function was declared inside the global scope, in the second inside the wrapper function scope.

window.name = "NoClosure";
(function(){
    var name = "Closure";
    arguments[0](); 
})(function(){console.log(name);}); //>"NoClosure"

window.name = "NoClosure";
(function(){
    var name = "Closure";
    (function(){console.log(name);})(); //>"Closure"
})();

If you inspect the of the callback with console.dir(), you can see that it has no closure, here a snippet if you want to test it yourself.

(function wrapper(){
    var isPrivate = "A closure could see me";
    console.dir(arguments[0]);
})(function callback(){});

Here is another experimental setup with 2 closures showing that function declared inside a call to a function are capable of getting a closure, but it will always be the closure of the scope of the function passing it, it can not access the scope of the function it was passed to as an argument and that later calls it as a callback.

(function outerScope(){
   var outerVar = "in outer scope";
   (function innerScope(cb){
       var innerVar = "in inner scope";
       cb();
   })(function callback(){
       console.log(
          "outer:"+ typeof outerVar,
          "inner:"+ typeof innerVar);
       console.dir(arguments.callee);
   })
})()

*source https://developer.mozilla.org/en-US/docs/Web/API/Window.name

Winchestro
  • 2,138
  • 14
  • 18
  • Ref: http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/ Callback Functions Are Closures When we pass a callback function as an argument to another function, the callback is executed at some point inside the containing function’s body just as if the callback was defined in the containing function. This means the callback is essentially a closure. Read my detailed post, Understand JavaScript Closures With Ease for more on closures. – Nishant Kumar Jun 08 '14 at 06:00
  • Can you give (or link) me an example of a callback function passed as an argument having a closure of the function it was passed to, because I fail to reproduce what you describe. – Winchestro Jun 08 '14 at 06:12
  • Ok I've read both articles, and your comment on it (which is a copy of what you wrote here), and still fail to follow your train of thought or reconstruct any case of callback closure. It would make my life a lot easier if I would, so please give me a hint how you manage to give a callback a closure. – Winchestro Jun 08 '14 at 06:30
  • @Nishant: "Callback Functions Are Closures when we pass a callback function as an argument to another function". Yes this is true, the callback is a closure. But it only "encloses" the environment it was defined in. It is not the same as a closure that was defined as in your example #2. You are confusing that the fact the argument passed into the function is a closure means it's the same as a closure defined inside the function. – Martin Konecny Jun 08 '14 at 17:49