I was reading the "Closures" section on the w3schools JavaScript tutorial and I don't understand how the last example works.
http://www.w3schools.com/js/js_function_closures.asp
The goal is to create a "private" variable counter
that only the add
function can manipulate. Here is the code:
<!DOCTYPE html>
<html>
<body>
<p>Counting with a local variable.</p>
<button type="button" onclick="myFunction()">Count!</button>
<p id="demo">0</p>
<script>
var add = (function outer() {
var counter = 0;
return function inner() {return counter += 1;}
})();
function myFunction(){
document.getElementById("demo").innerHTML = add();
}
</script>
</body>
</html>
I edited the two anonymous functions and named them outer
and inner
so they can be more easily referenced. Here is a link of the code in action:
http://www.w3schools.com/js/tryit.asp?filename=tryjs_function_counter3
So initially the variable add
is assigned to a self-invoking function expression. This would execute the outer
function one time and set the counter
to 0. When the button is clicked, myFunction
is called and this puts the returned value of the add
function, the updated counter
value, inside the p tag. So clicking on the button increments the value of the counter
variable by 1 on every onclick event of the button. I don't understand how the value of the counter
value is affected by the outer
and the inner
functions. This is how I (wrongly) understand it:
When the add
function is called by the myFunction
function (upon an onclick event of the button), first the outer
function would set the counter
variable to 0 by the following statement:
var counter = 0;
Intuitively I would think that the return value of the add
function would invoke the inner
function (especially because I can see this code works) but I don't get how. That is one question I have. If I just accept it then the inner
function would increment the counter
variable by 1. I can see how this makes sense for clicking the button that calls the myFunction
function once. For the second time the button is clicked I don't understand how it doesn't reset. I feel that before the second click the counter
variable is 1 and then on the click the outer
function resets the counter
variable back to 0 with this line again:
var counter = 0;
and then the inner
function is invoked. Since the inner
function is nested in the outer
function, it is in the scope to access the counter
variable and then increases it from 0 back to 1. What am I not understanding about this?
I feel I might not quite understand how the return
statement on a function works but I'm not sure. Is the add
variable just the inner
function only because that is what is returned? And how is it invoked if it is inside a return
statement? I don't get how var counter = 0;
is not executed on every click of the button when myFunction
is invoked.
I thought myFunction
invokes the add
function and that executes outer
function, which executes var counter = 0;
and then the inner
function gets returned and invoked and that increases the counter
variable.
I don't quite get if returning a function would invoke the function either. I also don't know if the creation and assignment of the add
variable had anything to do with how this works. I didn't think so at first but who knows? I don't understand this so anything is possible to me right now.