This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
I am trying to execute the following code:
for (var i = 0; i <= 9; ++i) {
State.prototype["button" + i.toString()] = function () {
console.log("I am a digit button" + i.toString());
this.setValue(i.toString());
};
}
But it is wrong, because the i variable is common for all the function created.
For example I want the function State.prototype.button0() to work as:
console.log("I am a digit button" + "0");
this.setValue("0");
How to do it?
Pass it to a function, so that the value of i doesn't change:
for (var i = 0; i <= 9; ++i) {
(function(i){
State.prototype["button" + i.toString()] = function () {
console.log("I am a digit button" + i.toString());
this.setValue(i.toString());
};
})(i);
}
Related
This question already has answers here:
How do JavaScript closures work?
(86 answers)
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 3 years ago.
I'm trying to figure out why this for loop does not render out 0,1,2,3 like its suppose to.
It renders 4, 4 , 4, 4.
How would i get this to print 0, 1, 2, 3 with the setTimeout still in place ?
for (var i = 0; i < 4; i++) {
setTimeout(function() {
console.log('The index of this number is: ' + i);
}, 3000);
}
Create another and call it on each iteration
function a(i)
{
setTimeout(function() {
console.log('The index of this number is: ' + i);
}, 3000);
}
for (var i = 0; i < 4; i++) {
a(i);
}
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
Why when I click on my buttons there are always 100 in console log? And how I can fix this?
function SampleFunction(param){
console.log(param);
}
for (i = 0; i < 100; i++) {
$("#btn-" + i).on('click',function(e){
SampleFunction(i);
});
}
use let keyword
for (let i = 1; i < 9; i++) {
$("#btn-" + i).on('click',function(e){
SampleFunction(i);
});
}
Pure js approach
let allButtons = document.getElementsByTagName('button');
for(i=0;i<allButtons.length;i++) {
allButtons[i].onclick = getPosition;
}
function getPosition() {
let position = Array.from(allButtons).indexOf(this) + 1;
console.log(`you clicked button at position ${position}`)
}
<button id="button-1">1</button>
<button id="button-2">2</button>
<button id="button-3">3</button>
<button id="button-4">4</button>
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
The following code works great. It pushes 10 unnamed functions into an array and then successfully executes the 7th item in the array.
var storeStuff = [];
for (let i = 0; i < 10; i++) {
storeStuff.push(function() {
console.log(i * i);
});
}
storeStuff[6]();
However the test function above is tiny. If I had a large function with many lines of code I'd likely want to declare it outside of the push.
For example what if I wanted to push a previously defined function and later invoke it like the example below?
var storeStuff = [];
function externalFunction(temp) {
console.log(temp * temp)
}
for (let i = 0; i < 10; i++) {
storeStuff.push(externalFunction(i));
}
storeStuff[6]();
Unfortunately this doesn't work as written and everything I've tried crashed and burned. What am I getting wrong?
Use function declaration as below
var storeStuff = [];
externalFunction = function(temp) {
console.log(temp * temp)
}
for (let i = 0; i < 10; i++) {
storeStuff.push(externalFunction);
}
storeStuff[6](6);
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
Im working with the gm npm module that deals with image manipulation. and i have this code.
for(i=0;i < 4;i++){
gm("www/img/" + image[i]).crop(550, 406, 0, 0).write(function(err) {
console.log(this.outname + " created :: " + arguments[3]); //success
});
}
this loop is meant to loop through the images array and crop each photo, but it only crops the last one. i think its something to do function invocation and callbacks, but not advanced yet for that level.
Change your code to:
for (var i = 0; i < 4; i++) {
(function (i) {
gm("www/img/" + image[i]).crop(550, 406, 0, 0).write(function(err) {
console.log(this.outname + " created :: " + arguments[3]); //success
});
}).call(this, i);
}
otherwise the value of i will be 3 each time your callback is being invoked.
You need to create a "closure" over the variable
Js has a function scope.
for (i = 0; i < 4; i++)
{
(function (a)
{
gm("www/img/" + image[a]).crop(550, 406, 0, 0).write(function (err)
{
console.log(this.outname + " created :: " + arguments[3]); //success
});
}).call(this,i)
}
or
that=this;
for (i = 0; i < 4; i++)
{
(function (a)
{
gm("www/img/" + image[a]).crop(550, 406, 0, 0).write(function (err)
{
console.log(that.outname + " created :: " + arguments[3]); //success
});
})(i)
}
edit :
Also - I would also keep a reference to the arguments since now , after IIFE - the arguments is changing.
you can keep your arguments via :
var args= Array.prototype.slice.apply(arguments)
example :
function g()
{
for (i = 0; i < 4; i++)
{
(function (a)
{
console.log(arguments); //huh ? arguments are not a,b,c !!! anymore
})(i);
}
}
g('a','b','c') // 0,1,2,3
so you do need to keep reference to the arguments cuz their changed after IIFE.
This question already has answers here:
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 9 years ago.
for (var i = 0; i < 10; i++) {
array.push($("" + i + ""));
$("#row").append(array[i]);
array[i].click(function () {
changeval(i);
console.log(i);
});
}
My problem is that the function changeval(i) becomes always the same value 10 of i.
I try to create buttons with onclick-function in this for-loop. I need a hint.
I would separate the initial adding of the buttons and the 'click' action.
for (var i = 0; i < 10; i++) {
array
.push($("<a href=\"#\" data-role=\"button\" data-inline=\"true\">"
+ i + "</a>"));
$("#row").append(array[i]);
array[i].click(function() {
changeval(i);
console.log(i);
});
}
Would be split up to:
for (var i = 0; i < 10; i++) {
array.push("<a href=\"#\" data-role=\"button\" data-inline=\"true\">"
+ i + "</a>");
$("#row").append(array[i]);
};
$('#row').on('click', 'a', function() {
changeVal($(this).text());
console.log($(this).text());
};
Also note that variables and functions within javascript should be written in CamelCaseForBetterReadability. Also note that I got rid of the $() surrounding the array items. Lastly, if you do not want to escape the quotations within your string, you can use a single quotation.
Look into JS closures, the value of i is set to the last iteration of the loop. Wrap that in a self-executing func with i as the param:
for (var i = 0; i < 10; i++) {
(function(i) {
array
.push($("<a href=\"#\" data-role=\"button\" data-inline=\"true\">"
+ i + "</a>"));
$("#row").append(array[i]);
array[i].click(function() {
changeval(i);
console.log(i);
});
})(i)
}
Use a closure, e.g.
for (var i = 0; i < 10; i++) {
(function(i) {
array[i].click(function() { . . . } );
)(i);
}
If you're using jQuery (seems like it if you're using .click :) you can use
http://api.jquery.com/jQuery.each/
to loop through elements and acheive this same functionality.