4

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.

4

I don't get how var counter = 0; is not executed on every click of the button when myFunction is invoked.

Because the code

var add = (function  outer() {
    var counter = 0;
    return function inner() {return counter += 1;}
})();

only executes once. It returns an immediate function, storing it into the add variable, which you then assign to something else later (using = Add()). Notice the ending pair of parentheses? That's what causes the outer function to execute immediately, one time.

When the function in the add variable is assigned, it returns the inner function. That inner function is what gets executed when myFunction runs.

The only other thing you need to know is that the inner function has access to the counter variable in the outer function, due to the closure.

  • Thanks Robert Harvey! That makes a lot more sense now. I wasn't understanding what the add variable actually stored but it is more clear now. Thanks again! – drj30026abanba Dec 10 '15 at 5:43
2

You are confused because you are thinking add is:

var add = (function  outer() {
             var counter = 0;
             return function inner() {return counter += 1;}
           })();

but actually add is:

add= function inner() {return counter += 1;}

because this function is what outer self executing function is returning and it is assigned to add.

Outer function is executed only once (when it is returning inner function) and initialized variable "counter" to 0.

Child function can access parent function's variable, and each time we are calling add, it just increment "counter" by 1.

1

add is holding a reference to the function inner i.e. function returned from outer function.

Closures is when a function remembers is its lexical scope even when invoked from outside that lexical scope.

So inner remembers its scope and thus able to access the counter variable . Thus , its inaccessible outside directly and acts as private. But add or inner can manipulate it.

As soon as you refer add to another type the scope in which counter resides gets garbage collected and gets lost.

I recommend you to read books from kyle simpson www.ydkjs.eu/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.