0

Please me to understand the closures. Why does the counter work in the first variant, but in the second version there is not?

var counter = (function(){
    var count=0;
    return function(){
       return count++;
    }
}());

console.log(counter());
console.log(counter());
console.log(counter());

The counter outputs 0,1,2

var counter = function(){
  var count=0;
  return function(){
     return count++;
  }
};

console.log(counter()());
console.log(counter()());
console.log(counter()());

The counter outputs 0,0,0

What is the difference?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 1
    In the first example the outer function is only called **once** and its return value is called 3 times (4 calls in total). In the second example, the outer function is called three times, therefore creating a new function each time that is subsequently called (6 calls in total). – Felix Kling May 30 '18 at 18:16
  • 2
    Possible duplicate of [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Heretic Monkey May 30 '18 at 18:16
  • 1
    If you step through the code in a debugger, you'll see why. Every time you call `counter()` in the second instance it's calling `var count = 0;`. – Heretic Monkey May 30 '18 at 18:18
  • Both Mike and Felix are correct - but Mike's answer is the real reason. In the second example, each time you call `counter()` a new `count` variable is created. In the first example, `count` is scoped in the same block where the function actually assigned to the `counter` variable is created (the Immediately Invoked Function block) – Tibrogargan May 30 '18 at 18:23

2 Answers2

1

In the first example, you are using an Immediately Inovked Function Expression. This is calling the function inline and assigning the resultant function to counter. Each time you call counter() you are calling that inner function which has the count variable in scope.

The second example is equivalent to writing as

function counter() {
  var count=0;
  return function(){
     return count++;
  }
}

When you write it this way, it's clearer that every time you call counter(), you are returning a new function with the count variable in scope

You could do the equivalent in the second example by assigning the result to a variable and calling that multiple times.

var counter = function(){
  var count=0;
  return function(){
     return count++;
  }
};

var counterObj = counter();

counterObj(); // returns 0
counterObj(); // returns 1
counterObj(); // returns 2
Zeph
  • 1,728
  • 15
  • 29
  • Do you think it would be maybe clearer to reverse the naming of `counter` and `counterObj` to make the example more closely match the question? (Also perhaps even do: `var counter = (counterObj)();`) – Tibrogargan May 30 '18 at 18:33
-1

In the first example, counter is assigned the return value of a self invoking function.

counter =(

In the first example, counter is called and it returns

return count++;.

In the second example, counter is a regular function, and when called begins at the declaration

var count=0;
L0uis
  • 703
  • 5
  • 8