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
Related
In summary I have the following code:
let incrementer = (function() {
let counter = 0;
let IncreaseCounter = () => {
return counter += 5;
}
return IncreaseCounter;
})();
console.log(incrementer); // function body () => {}
console.log(incrementer()) // 5
console.log(incrementer()) // 10
console.log(incrementer()) // 15
incrementer doesn't work even though i had it wrapped in an IIFE.
Is there any way to print out incrementer as a variable to be incremented each time, without the invocation ()?
Is there any other way in Javascript to achieve such goal other than that closure approach?
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:
addEventListener calls the function without me even asking it to
(5 answers)
Closed 3 years ago.
How can I pass a variable to the onclick function? When using
var number = 123;
document.getElementById('myButton').onclick = myFunction(number);
It will run that function before even clicking the button because the function will be called and the return value will be put into the onclick, which doesnt help me
Without the "()" it will only call the function once I click the button, but how do I pass a variable then ?
var number = 123;
document.getElementById('myButton').onclick = myFunction;
function myFunction(i) {
i += 10;
alert(i);
}
One option would be to make the onclick an anonymous function to call myFunction.
var number = 123;
document.getElementById('myButton').onclick = () => {
myFunction(number)
}
function myFunction(i) {
i += 10;
alert(i);
}
<buton id="myButton"> Test button </buton>
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.