Javascript closures for iterated function definitions [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript closure?
This has probably been asked before, but...
If I want a list of functions
var funs = [
function(){ console.log(1); },
function(){ console.log(2); },
function(){ console.log(3); },
function(){ console.log(4); },
function(){ console.log(5); } ]
it would seem that one could make it by something like:
var funs = [];
for(var i=1; i <= 5; i++){
funs.push(function(){ console.log(i) };
}
Which doesn't work, as the variable i is a single variable bound to all the functions, so that
funs[0](); funs[1](); funs[2](); funs[3](); funs[4]();
outputs
6
6
6
6
6
not
1
2
3
4
5
This isn't the output I want. I guess I need to force javascript to bind a copy of the value of i at the time the function is created, instead of closing with the reference for i. How would I do this?

The easiest way is passing the function through the argument of a self-executing function:
for(...) {
(function(i) {
// here you have a new i in every loop
})(i);
}

Related

behavior of javascript 'this' keyword in closure [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 4 years ago.
Consider a simple pattern where we call setTimeout within a loop to print the loop counter:
function g(i){
return function()
{
console.log(i);
}
}
for(i=0;i<4;i++)
{
setTimeout(g(i),3000);
}
This returns the expected result:
0
1
2
3
According to my understanding, this function should do the same thing
function f(i){
this.n = i;
return function()
{
console.log(this.n);
}
}
for(i=0;i<4;i++)
{
setTimeout(f(i),3000);
}
Instead, I get varying results, in NodeJS:
undefined
undefined
undefined
undefined
And in Google Chrome:
3
3
3
3
Neither of these results make sense to me, so I was hoping someone else can explain this to me.
You can use an arrow function to keep your this:
function g(i){
return () =>
{
console.log(i);
}
}
for(i=0;i<4;i++)
{
setTimeout(g(i),3000);
}

how to create dynamic function in javascript with for loop and its index inside function [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
var data = ["s","a"]
var asyncFunctionss = [];
for (var i in data) {
asyncFunctionss.push(function (callback) {
console.log(i);
});
}
for (var g in asyncFunctionss) {
asyncFunctionss[g]();
}
I try to run this program it give the following output.
Expected Output
0
1
Actual Output
1
1
How to achieve the Expected output ?
You need an IIFE. The reason is that as soon as a function element in asyncFunctionss is called the variable i is already 1. You could use a IIFE to remember the value of variable i:
var data = ["s","a"]
var asyncFunctionss = [];
for (var i in data) {
(function(i){
asyncFunctionss.push(function (callback) {
console.log(i);
});
})(i);
}
for (var g in asyncFunctionss) {
asyncFunctionss[g]();
}

Javascript iterator design pattern [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
How do JavaScript closures work?
(86 answers)
Closed 7 years ago.
I am confused why the following code snippet has (i) at the end of it:
for (var i = 0; i < 10; i += 1) {
(function(i) {
setTimeout(function() {
console.log(i);
}, 1000);
})(i);
}
Ive seen it in production code Ive worked on--I just can intuit why it's necessary.
You are defining an inline function, so you could force the i parameter to be in the local scope at the time of the execution of the console.log statement. By adding the parameter, you are creating a self executing function. Similar would be the following statements, which might be better to read...
function logmeWithTimeOut(value) {
setTimeout(function() { console.log(value); }, 1000);
}
for (var i = 0; i < 10; i++) {
logmeWithTimeout(i);
}
Though I might prefer
function logmeWithTimeout(value) {
console.log(value);
}
for (var i = 0; i < 10; i++) {
setTimeout(logmeWithTimeout.bind(undefined, i), 1000);
}
It forces the i to be in local scope, otherwise your log would print only 11
Because you are defining a function inside the parenthesis, and then you are calling it passing i as parameter.
If you didn't put the (i) there, you would just define a function but never call it.

Understanding closures in JavaScript [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
Consider this
fs=[];
for(var i = 0; i < 3; i++){
fs.push(function(){
return i;
});
}
console.log(fs[0](),fs[1](),fs[2]())
I thought that i would be in the closure of the function so that this would print "0 1 2", but nope... it prints "3 3 3".
Why doesn't this work? And is there any way to make this work?
You are actually pushing three instances of the same anonymous function into your 'fs' array. Then your log statement calls that function three times. At the time you are calling it, the loop has completed and the value of 'i' within the closure is 3, so that's what is returned.
I'm not sure what you mean by "work", but maybe something like this is what you mean:
fs = [];
function closureFunc(myVal) {
return function () {
return myVal;
}
}
for (var i = 0; i < 3; i++) {
fs.push(closureFunc(i));
}
console.log(fs[0](), fs[1](), fs[2]());
This creates three separate closures where the function you are pushing has the scope of the declaring function "closureFunc". Within those closures the myVal is set to the value that was passed in.
Javascript doesn't have a notion of block scope, it only has function scope. Hence the placement of the var i is meaningless in terms of lifetime. It may as well have been the first line in the method.
In order to fix this you need to declare a new scope that holds a separate i value
fs=[];
var makeFunc = function(j) { return function() { return j; } }
for(var i = 0; i < 3; i++){
fs.push(makeFunc(i));
}

how to get exact value in setTimeout function [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
javascript using settimeout() with a loop
(4 answers)
Closed 9 years ago.
Simple question...
for (var i = 0; i < 5; i++) {
setTimeout(function () { alert(i) }, 3000);
}
how to alert 5 times with exact value of i.
It gives "5" only 5 times.
I need its result like
0
1
2
3
4
With a closure that keeps the value of the variable constant within the new scope of the immediately invoked function
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function () { alert(j) }, 3000);
}(i));
}
The setTimout is asynchronous, so by the time it executes the loop has long since completed, and the value of i has been changed to 5, so you need to lock it in.
You can use setInterval alternate to setTimeout
Try,
var xCnt = 0;
var xInterval = setInterval(function()
{
xCnt +=1;
alert(xCnt);
if(xCnt == 5)
{
clearInterval(xInterval);
}
}, 3000);
DEMO

Categories

Resources