Set Value of Variable on first instance of function running - javascript

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++;
}
})();

Related

Variables in a IIFE

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.

counter increase each time loads the function

I am pretty new into javascript , but I am trying to create a counter , but when I setup my counter . it looks gives me the same value , but I want first round 1 then 2 then 3 to n-1
function timer(){
var contactsNum = 0;
contactsNum++;
console.log(contactsNum)
}
(function loop() {
setTimeout(function () {
timer()
loop()
}, 9000);
}());
This is because variable contactsNum is local to the function timer, and every subsequent call of function timer will initialize the value 0. If you want to keep track of the value you can use closure.
The problem is here:
function timer(){
var contactsNum = 0;
contactsNum++;
console.log(contactsNum)
}
You are defining and assigning a variable in timer. That means, everytime timer gets called, contactsNum gets set to 0.
You need to put it outside of the function like:
let contactsNum = 0;
function timer() {
contactsNum++;
console.log(contactsNum)
}

Closures in javascript, when are they in effect?

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.

Understanding JavaScript Closures - Freeze variable passed to callback

I do not yet have a basic understanding of JavaScript closures;
I have a question regarding a specific situation that perhaps is also basic and common example:
Count from 1 to 3 in 3 seconds
See JSFiddle here: http://jsfiddle.net/nAh8x/
The code:
var i,
t;
t = 0;
// Case A
for( i=1; i<=3; i++ ) {
setTimeout( function() { log(i); }, t );
t += 1000;
}
// Case B
for( i=1; i<=3; i++ ) {
setTimeout( wrapper(i), t );
t += 1000;
}
function wrapper(i) {
return function() { log(i); };
}
// Log utility function
function log(msg) {
$('#log').append( msg + '<br />' );
}
Case A doesn't work.
It's clear to me why: every time the function inside setTimeout is called and accesses the i variable, its value has already reached 4.
Case B works.
When wrapper(i) is called it returns
function() { log(i); };
and the above return value (a function) is what goes inside setTimeout. What goes inside setTimeout is exactly the same as Case A
But this time, the i variable have been "frozen" with the value at the time of the call.
Why using the wrapper function let the passed value to be frozen?
That's not completely clear to me.
Closure is an environment which is created with variables scope and nested function by calling of outer function,
Every time the wrapper() is called there would created each different environment for below's function
function wrapper(i) {
return function() { log(i); };
}
Here is the i's value would be same as when wrapper() is invoked. Each time the i's value would be private for that particular environment which made by invoking wrapper() outer function.
The wrapper function has it's own i that is locally scoped to it.
This receives the value of the other i at the time wrapper is called.
It might be clearer if you rewrote it as:
function wrapper(notI) {
return function() { log(notI); };
}
The variable i used inside wrapper is the one the has been passed (as a copy) as the formal parameter to wrapper. It's not the same i as the one inside your for loop - you could rename that variable to anything you like and the code would still work.
It's frozen because it has the value it had each time wrapper was originally called.

Is it possible to call a clearInterval method on a setInterval variable that is out of scope?

I have a setInterval function that is initializing a varibale with it's id in a for loop, which results in a number of setInterval functions executing in the for loop. Each of the setInterval functions will be assigned to a variable now my question is, is it possible for one single variable to contain the values of all of the setIntervals id's or only one? If all of the id's can all be contained in a single variable is it possible to clear certain setIntervals via there id that is contained in the variable or will I need to declare a unique variable for each setInterval to be able to do this?
var intervalId;
for(var i = 0; i < 10; i++) {
intervalId = setInterval(function() {}, 100);
}
The values returned from setInterval and setTimeout are numbers, so only one will "fit" in a variable.
You could make an array:
var intervalId = [];
for(var i = 0; i < 10; i++) {
intervalId.push( setInterval(function() { ... }, 100) );
}
Note that there's something important missing from your question, and that's the code in the interval function. Specifically, if that code wants to refer to "i", there's a problem: all of the separate functions will share the same "i" variable (the one declared in the loop header).
To get around that, you could do this:
function makeTimerFunction(i) {
return function() {
// the code
if (whatever) { clearInterval(intervalId[i]); }
// and so on
};
}
var intervalId = [];
for (var i = 0; i < 10; i++)
intervalId.push( setInterval( makeTimerFunction(i), 100 ) );
By using a separate function, you create another scope and can "freeze" each value of "i" in a separate, per-timer variable.
edit — #pst points out correctly that if it is really the case that you do want to refer to the timer id from inside the handler functions, then there's really no need for that "intervalId" array at all - you could just use the wrapper function to isolate the call to setInterval().
function createTimer() {
var timerId = setInterval(function() {
// the code
if (whatever) { clearInterval( timerId ); }
// ...
};
}
for (var i = 0; i < 10; ++i)
createTimer();
That way each timer is set up with it's own private timer ID variable. Of course, if you do need the timer id outside the function, then you need an external cache for the ids.

Categories

Resources