0

After reading around in SO and this good article, I still quite didn't understand the scope of local variables. I also read this good article from Ben Alman.

function foo(){
  var i=0;
  console.log(++i);
}
foo(); //1
foo(); //1

//##################

var foo = function(){
  var i=0;
  console.log(++i);
};

var x = foo;
x(); //1
x(); //1

//##################

function foo2(){
  var i = 0;
  return function(){
     console.log(++i);
  };
}

var x = foo2();
x(); //1
x(); //2 -- I don't get this

Why on the third example, it seems that I can have a singleton function, with the same common internal variable after calling it several times, even if it calls i=0?

Aónio
  • 579
  • 4
  • 13
  • 1
    Third example behaves as a class where var i = 0; is private variable. And each time you execute x() it will trigger return function and increase value of that private value. in order to get result 0 each time you should call foo2()(). – Aleksandar Gajic Aug 11 '17 at 09:20
  • 1
    as you can see. you returned an anonymous function from `foo2()` which has an `i` that is being referred inside of it. so everytime you call the anonymous function. you're incrementing the value inside the `foo2()` – Semi-Friends Aug 11 '17 at 09:20
  • 2
    @AleksandarGajic: No, not a "class." Just a closure over the context of the call to `foo2`. – T.J. Crowder Aug 11 '17 at 09:20
  • 2
    "I still quite didn't understand how local variables behave whether is a function declaration or function expression" wrt your sample code they behave the same. – Yury Tarabanko Aug 11 '17 at 09:21
  • 1
    @Yury exactly right - this isn't an issue of scoped variables behaving differently if they're used in named or anonymous functions, this seems to be an instance of misunderstanding closures. – Andy F Aug 11 '17 at 09:26
  • @Semi-Friends, why is anonymous? What part of the code makes `foo2` or `x` anonymous? – Aónio Aug 11 '17 at 09:28
  • 1
    the returned function has no name, which makes it anonymous – Semi-Friends Aug 11 '17 at 09:29
  • @YuryTarabanko, you're right. Edited accordingly – Aónio Aug 11 '17 at 09:31
  • 1
    Keep in mind that not only "i" in last example can be in the scope chain of returned function, but possibly other variables and functions in external contexts. The best article I ever read about this is http://dmitrysoshnikov.com/ecmascript/chapter-4-scope-chain/ Happy coding! – zhibirc Aug 11 '17 at 09:44

1 Answers1

3

That because you are invoking the internal function several times which is returned by the main function and the main function(foo2) only executed once. Hence there is no resetting happening and i keep getting increased.

So foo2() gets called once and the internal function calling twice.

var x = foo2();

When you do that i gets initialized to 0 and returning a function. Note that you are not touching this function anymore and going to use only the returned function.

   x();

That line executing the returned function and which just executing the line

console.log(++i);

x(); 

Same again.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 1
    "That because you are invoking the internal function several times and the main function only executed once". And why is that? – Aónio Aug 11 '17 at 09:21
  • 1
    @Aónio I'll update it with more description. – Suresh Atta Aug 11 '17 at 09:22
  • @Aónio Because you're calling foo2 as a function in the third example (`var x = foo2()`) so x is set to the return value of foo2, rather than your second example where x is a _reference_ to the foo function (`var x = foo`) – Andy F Aug 11 '17 at 09:23
  • actually as per the code, there will be no resetting that will happen. only re instantiation of the function – Semi-Friends Aug 11 '17 at 09:23
  • 2
    We don't need another hyper-brief explanation of closures. We already have in-depth explanations in [this question's answers](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work). – T.J. Crowder Aug 11 '17 at 09:26