Why does the variable counter keep increasing when it re-initializes itself back to 0 in the self-invoking function?
var add = (function () {
var counter = 0;
return function () {
return counter += 1;
}
})();
add();
add();
add();
// the counter is still 3 when this line of code exists
// var counter = 0;
So when add() function gets invoked, a function runs first with initializing counter = 0 and returning another function that returns the incremental value of counter. Why is this the case when there's var counter = 0; ?
source: https://www.w3schools.com/js/js_function_closures.asp
edit: November 16th, 2017
Okay so it makes a lot more sense now from both of the answers given on this page. For extra clarification, I will add my own reasoning to give it a better visualization of why this happens.
//first call of add()
(function(){ // a self-invoking function
var counter = 0; // executes once with the self-invoking function
return function() { return counter += 1; } //explained below
});
//since the self-invoke function ran already, add() will begin to run the returned function:
add = function() { return counter += 1; };
add(); ----> counter += 1; -----> add.counter = 1;
//counter acts like this.counter, so it's a part of add()
//counter is now at 1
//second call of add();
//add has now officially been **transformed** to the new function:
add = function() {
return counter += 1;
};
//while add.counter still **exists** and remains in the self-invoke
//function. Do we call this **limbo variable** ? Don't know.
//add.counter is at 2
//third call of add();
function() {
return counter += 1;
}
//add.counter is at 3!
Please note that "var add" assigned a self invoking function that returns a function.
Whatever above the return statement is the self invoking function closure. Which means that it is available to the returned function.
So it is in fact only initialized once. And then the return function, which is what the variable "add" now contains, increments the counter whenever it is invoked.
Because the variable add contains the result of the self invoking function. So the value of add is this:
function () {
return counter += 1;
}
The counter variable is only initialized before this function is set to the add variable.
Related
I am trying to understand closures in Javascript. I came across this example :
var add = (function () {
var counter = 0;
return function () {counter += 1; return counter}
})();
add();
add();
add();
I do not understand why counter value comes to be 3. I can clearly see that counter is being intialized with 0 each time the function is called.
Let's have a look at what gets interpreted in which order.
Step #1:
In var add = (something)(), the first thing to be evaluated is the "something".
Step #2:
Once evaluated as a valid function, there is a reference to it which is not yet stored in a variable and never will because the function is getting executed right away due to the second set of parenthesis.
Step #3:
That function does 2 things:1) it assigns 0 to the counter variable.2) it declares another function: function () {counter += 1; return counter}. The reference to that function is what will be assigned to the add variable.
Step #4:So each times add() is called, what is executed is counter += 1; return counter.
Scope:
The counter variable only exist in the outer and inner functions. The outer function never had its reference stored to a variable because it was immediately called, so it never will be called again. The inner function reference was stored in add and can be called again.
var add = (function () {
var counter = 0;
return function () {counter += 1; return counter}
})();
// Notice that add is the "inner" function
console.log(add)
// What is returned by add is the counter value
var firstCall = add();
var secondCall = add();
var thirdCall = add();
console.log(firstCall, secondCall, thirdCall)
// the counter does not exist outside the scope of the inner function
console.log(typeof(counter))
A good reference I can suggest to learn more about how JS is interpreted is Wakata.io... Particularly the CompuThink section for your question.
The function within the parentheses, followed by another pair of parentheses is an IIFE - immediately invoked function expression.
//immediately invoked function expression
(function() {
var counter = 0;
return function() {
counter += 1;
return counter;
}
})();
This is called so because this function gets called immediately after it is defined.
The variable add is not assigned the IIFE. Rather, it gets the result of the invoked function as below.
function() {
counter += 1;
return counter;
}
A closure is the means by which a function has access to the scope in which it is created.
This function has access to counter variable in the IIFE because of closure behaviour. Even though IIFE's life time is already over, the function in add variable has access to it due to closure.
Whenever we are calling add(), it is actually updating the counter in IIFE. All the while, IIFE was never executed again. It ran only once during the initial phase.
I have referred to multiple links for this concept but it is little bit tricky to wrap the concept around the head completely.
I was going through and example of it on https://www.w3schools.com/js/js_function_closures.asp
var add = (function () {
var counter = 0;
return function () {counter += 1; return counter}
})();
add();
add();
add(); //Counter is 3
But isn't every time this is getting called counter is getting reinitialized to 0?
Can someone use table or something to help me understand every step here?
What add holds is returned function in the IIFE. (https://developer.mozilla.org/en-US/docs/Glossary/IIFE)
function () {counter += 1; return counter}
So calling add doesn't reinitialize counter.
var add = (function() {
var counter = 0;
return function() {
counter += 1;
return counter
}
})();
console.log(add());
console.log(add());
console.log(add());
var addHandler = function() {
var counter = 0;
return function() {
counter += 1;
return counter
}
};
const add = addHandler(); // return inner function
console.log(add());
console.log(add());
console.log(add());
In javascript, functions have their own execution environment.
And the execution environment is created when the function is called and disappears when execution is complete.
In the code above, the value in "add" becomes the new function returned after the IIFE function is executed.
In other words, the execution environment of the IIFE function has already been executed and disappeared.
However, the inner returned function is still looking at the parent function's variable "counter".
Previously, it was said that the environment disappears when the function is called. In this case, the remembering the environment of the parent function is called a'closure'.
IIFE is an immediate function.
Functions are declared and called when necessary in the form of "function name()".
The IIFE above will execute the function right away by declaring the function and wrapping it in "()".
This question already has answers here:
Why do javascript variables in closure functions not reset to a default when called multiple times?
(2 answers)
Closed 2 years ago.
Simple JS logic question here.. In the below code, why does add() only set counter to 0 once? I feel like every time the function is called it should reset it to zero.
var add = (function () {
var counter = 0;
return function () {counter += 1; return counter}
})();
add(); // 1
add(); // 2
Thanks!
You're misunderstanding the code. The function add() does not contain the code var counter = 0.
Here's a rewrite of the exact same code that makes it more clear:
var add;
// Note: THIS function is NOT add()
(function () {
var counter = 0;
// THIS function is add()
add = function () {counter += 1; return counter}
})();
add(); // 1
add(); // 2
The code above does exactly the same thing as your original code except for how add was assigned. In your code it was assigned via a return value but in the above I simply assigned it directly as a global variable to make it more clear which function is add().
Another way to look at it that is more like your original code is to explicitly name the two functions:
var function1 = function () {
var counter = 0;
// The returned function is what will be assigned to add()
return function () {counter += 1; return counter}
}; // Do not call it yet since calling it was what was confusing you
var add = function1();
add(); // 1
add(); // 2
I've been trying to learn about closures, but one thing still perplexes me. If I have the following code:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
// Returns "3"
If I call add() three times, why dosen't it set counter to zero every time, then return the anonymous funtion that increments counter by one? Does it skip over it once the self-invoking function runs? Sorry if the question seems simple, I'm having a hard time understanding it. Any help would be greatly appreciated.
If I call add() three times, why dosen't it set counter to zero every time, then return the anonymous funtion that increments counter by one?
Because add is that anonymous function, because the function containing counter got called and its result was assigned to add:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
//^^----------- calls the outer function, returns the anonymous inner function
If you didn't call it:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
});
//^--- no () here
...then add would do what you said, it would return a new function with its own counter, each time you called it:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
});
var a = add();
var b = add();
var c = add();
console.log("a's first call: " + a());
console.log("a's second call: " + a());
console.log("a's third call: " + a());
console.log("b's first call: " + b());
console.log("b's second call: " + b());
console.log("b's third call: " + b());
console.log("a's fourth call: " + a());
console.log("b's fourth call: " + b());
.as-console-wrapper {
max-height: 100% !important;
}
That's not resetting counter, that's creating a new counter each time.
By calling add() you are not actually executing outer function but instead you are executing inner function. For inner functtion, counter is like a global variable that has been set once to 0 and then it was never set again to 0. On calling add() you are executing lines inside inner function thus increamenting counter.
The value assigned to add is the result of the IIFE, in which the closure was created. Maybe it's more obvious what will happen when add() is called, when its creating is written as follows (equivalent to your original code):
var add;
(function () {
var counter = 0;
add = function () {return counter += 1;};
})();
For example I have a variable which should increment every time the function is run. I want the variable to initially be given the value of 0, but then increase by 1 every time the function is called. I do not want to give the variable global scope, however obviously if I declare it within the function it is going to be reset to 0 every time it is called.
Is there a simple and efficient way to to do this in Javascript?
My Javascript:
function myFunction(){
var i=0;
//Body of function
i++;
}
You can set the value on the function object itself, like this
function myFunction() {
myFunction.i = myFunction.i || 0;
myFunction.i++;
}
Alternatively, you can use closure, like this
var myFunction = (function () {
var i = 0;
return function () {
// `myFunction` will be this function only and it increments the
// `i` from the enclosed function.
i++;
}
})();