I have a modal dialog with a submit button, which when clicked caused the following code to execute:
$("#addqueuebutton").on("click",function(){
var counter = 0;
return function(){
counter += 1;
...
alert(counter);
};
});
I have to ensure that the counter is initialised only once, and so I tried to use a closure. But the code is not executing properly as the alert box does not appear. I tested the code on online compilers and it appears to be correct. Can someone tell me if there is something wrong in my syntax?
You're assigning the wrong function to click. When you click, you initialise counter and then return the inner function.
You need to call the outer function and assign its return value to the second argument of on().
}); should be }());
Or, to make it clearer:
function create_counter(){
var counter = 0;
return function(){
counter += 1;
...
alert(counter);
};
}
var counter_incrementing_function = create_counter()
$("#addqueuebutton").on("click", counter_incrementing_function);
Related
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 "()".
I am new to js and I am experimenting with closures. There is something I can't get my head around.
If I write
var uniqueInteger = (function() { // Define and invoke
var counter = 0; // Private state of function below
return function() { return counter++; };
}());
and I repeatedly call the function as uniqueInteger() I obtain 0,1,2,3 and so on. It seems then that counter is not destroyed after the function is called. Where is it stored since it is not a global object?
Now, if I slightly change the code and define uniqueInteger as
var uniqueInteger = (function() { // Define and invoke
var counter = 0; // Private state of function below
return function() { return counter++; };
});
and I repeatedly call uniqueInteger()() the value which I obtain is constantly 0. How is that possible?
Where is it stored since it is not a global object?
In the scope created by the closure.
Now, if I slightly change the code … the value which I obtain is constantly 0. How is that possible?
Because every time you call var counter = 0; in the second chunk of code, you rerun the expression var counter = 0; (you also create a new scope and return a new function which you immediately call because you had ()()).
In the first chunk of code you ran that function once and assigned its return value to uniqueInteger, so the expression that set counter to 0 was only evaluated once.
I would like to make something that comes up after user right-clicked many times (5 clicks, for example). Then a div should be shown.
Right now I'm using this code:
document.oncontextmenu = function() {
$("#red").fadeIn(500).show().delay(3000).fadeOut(800);
return false;
};
This works fine, but it misess five attempts like I have said in my request.
UPDATE: Here the right code!
document.oncontextmenu = (function() {
var counter = 0;
return function() {
counter++;
if (counter == 5) {
$("#red").fadeIn(500).show().delay(3000).fadeOut(800, function() {
counter = 0;
});
}
return false;
};
})();
Thanks to #James Thorpe
Use what you have, but wrap it in a closure that has a variable to count how many times the inner function has been executed:
document.oncontextmenu = (function() {
var counter = 0;
return function() {
counter++;
if (counter == 5)
$("#red").fadeIn(500).show().delay(3000).fadeOut(800);
return false;
};
})();
Note that the outer function is invoked immediately to create the variable, then returns the inner function as the event handler. By using such a closure, we keep everything related to the event (including the counter variable) within the local scope without leaking anything to the global scope.
If you want to be able to invoke the div multiple times, you just need to reset the counter each time it's shown. The best place to do that is in the callback function supplied to the fadeOut function, so that the count only begins again once the div has been hidden.
if (counter == 5) {
$("#red").fadeIn(500).show().delay(3000).fadeOut(800, function() {
counter = 0;
});
}
Looks like for some reason my code cannot keep track of a local variable i being incremented and it always return its initial value 0.
Here is JSFiddle where I played around http://jsfiddle.net/ou2uxwn5/20/
var counter = function(){
var i = 0;
console.log(i);
return function(){
i++;
return i;
};
};
Not sure if garbage collector eats it up, though behavior is the same with var calls being defined too (I would expect this to create reference and not to throw local variable i into trash bin).
What is wrong with the code and why?
You should execute the first function immediately to avoid any confusion down the line. This will return a new function and assign it to counter.
var counter = (function(){
var i = 0;
console.log(i);
return function(){
i++;
return i;
};
})(); // logs 0 in the console
Calls to counter() will increment i and return it's value.
console.log(counter()); // logs 1 in the console
console.log(counter()); // logs 2 in the console
I suggest you read about closures to get a better understanding of how they work. Here is a good place to start.
problem solved:
1) should call "calls()" instead of "counter()"
2) moved console.log(i) into return statement.
I have problem for increase number in one unit when i call function and onclick event
I have this:
function caller() {
counter = 0;
alert("ok" + counter);
jQuery(".db_header_general" + number).click(function() {
alert("ok" + counter);
counter++;
});
}
In this case if i call the function always the alert tell me "0" and if i call function and use the event onclick yes the result it´s right 1 ,2 ,3 ,4 , etc , the problem it´s if i go and activate the function no continue from the last counter number and always show "0"
I need for example call function and show 1 ,2 ,3 and if event click it´s activate continue and add +1 from the last counter number , but the problem - and i can´t get works - . it´s no continue with the last number
Also i try this
function caller() {
counter=0;
alert("ok"+counter);
jQuery(".db_header_general"+number).click(function() {
alert("ok"+counter);
});
counter++;
}
Using counter outside of click event, but also the same result and no works for me
Thank´s and the best regards for the help
You should place counter outside the function. With current functionality when ever you call the function the counter value sets to 0. Do it like this
var counter = 0;
function caller ()
{
// functionality
counter++;
}
counter=0
gets executed every time you call your function because it's a local variable. So every time you call your function, you set the counter to 0. Make counter a global variable and it'll work.
Example added:
<script type="text/javascript">
var counter = 0;
function caller(){
alert("ok"+counter);
jQuery(".myBtn").click(function() {
alert("ok"+counter);
counter++;
});
}