Save value of variable within callback [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I have the following code:
<div id="0">click here</div>
<div id="1">click here</div>
<div id="2">click here</div>
for(var i=0;i<3;i++){
document.getElementById(i).addEventListener("click",function(){
alert(i);
});
}
How can I get my callback function to alert 1, then 2 and then 3? It always alerts 3, and I need a way for it to save the value of 'i' at each iteration.

for(var i=0;i<3;i++) {
document.getElementById(i).addEventListener("click", (function() {
var j = i;
return function() {
alert(j);
}
})();
);
}
Also this one should work:
for(var i=0;i<3;i++) {
document.getElementById(i).addEventListener("click", (function(j) { alert(j); }).bind(undefined,i));
}

A global counter variable can be used to count the number of clicks.
var counter = 1;
for(var i=0;i<3;i++){
document.getElementById(i).addEventListener("click",function(){
alert(counter++);
});
}

Related

Why it says push is not a function when called? [duplicate]

This question already has an answer here:
Why does [].push([]) return 1? [duplicate]
(1 answer)
Closed 3 years ago.
function rotLeft(a, d) {
var temp=[];
temp=a.splice(0);
for(let i=0; i<d-1; i++)
{
var first=temp.shift();
temp=temp.push(first);
}
var result=temp;
return temp;
}
if you know the rotate left problem in hackerrank, why woudnt this code work. The console says push is not a function. whats wrong in this code. Also please explain arr.shift(arr.push(arr[0])); this line. The first element is pushed to the last element and the first element is removed?
It should be temp.push(first); not temp=temp.push(first);
function rotLeft(a, d) {
var temp=[];
temp=a.splice(0);
for(let i=0; i<d-1; i++)
{
var first=temp.shift();
temp.push(first);
}
var result=temp;
return temp;
}
console.log(rotLeft([1,2,3,4,5,6],8))

Javascript how to pass index value of a class to another class inside a function? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I'm trying to preview image in specific class that has the same index value of another class, from where the user selects an image.
So far I have done this. When I give a specific value to the output class index the image shows up in that specific class
var input = document.getElementsByClassName("input");
var output = document.getElementsByClassName("output");
for (i = 0; i < input.length; i++) {
input[i].onchange = function() {
output[0].src = URL.createObjectURL(event.target.files[0]);
}
}
However when I try to pass the 'i' variable to that class's index the code doesn't work.
var input = document.getElementsByClassName("input");
var output = document.getElementsByClassName("output");
for (i = 0; i < input.length; i++) {
input[i].onchange = function() {
output[i].src = URL.createObjectURL(event.target.files[0]);
}
}
How can I solve this?
In this code you have used a closure function.When the function is invoked, it is created a single context.
Read more about, here.
One method is to use Immediately-invoked function expression, something like this:
for (i = 0; i < input.length; i++) {
(function(index){
input[index].onchange = function() {
output[index].src = URL.createObjectURL(event.target.files[0]);
}
}(i));
}
Here is an example where closures are used in wrong way.
var input=document.getElementsByClassName('abc');
for (i = 0; i < input.length; i++) {
input[i].onclick = function() {
console.log(i);
}
}
<button class="abc">Button1</button>
<button class="abc">Button2</button>
<button class="abc">Button3</button>
As you can see, anything button you clicked, console.log display 3.
Why it is this behavior ?
It is created a single context. When for loop is finished, the value of i remain 3 and whenever you clicked one button, this value is display in console.
How can we resolve this problem ?
One method is to use IIFE, as I mentioned above.
var input=document.getElementsByClassName('abc');
for (i = 0; i < input.length; i++) {
(function(index){
input[index].onclick = function() {
console.log(index);
}
}(i));
}
<button class="abc">Button1</button>
<button class="abc">Button2</button>
<button class="abc">Button3</button>

Passing array and index within `for` loop and `setTimeout()` [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I would like to execute a click on templates[i] within setTimeout within a for loop
for(var i=0; i<templates.length; i++){
setTimeout(function(){
(function(){
templates[i].click();
}(i, templates));
}, 200);
}
I get the error templates[i] is undefined.
However, something like this works fine:
for(var i=0; i<templates.length; i++){
setTimeout(function(){
(function(){
console.log(templates_arr+templates)
}(templates_arr, templates));
}, 200);
}
Can anybody shed some light onto why this is like this and how I can pass the array and index properly?
Thanks,
Dan
it should be
for(var i=0; i<templates.length; i++){
(function(i,templates){
setTimeout(function(){
templates[i].click();
}, 200);
})(i, templates);
}

Passing a variable to a click function created in for loop [duplicate]

This question already has answers here:
Javascript multiple dynamic addEventListener created in for loop - passing parameters not working
(5 answers)
Closed 7 years ago.
Basically I created a bunch of cells and I am trying to add onclick to each one passing a variable to use inside the function. But doing straight up passes the 'i' variable as the last i value and not 0,1,2,3,4 etc. Here is a snippet of what I am doing.
for (var i = 0; i < cellCount.length; i++) {
var cellName= "cell"+ i
document.getElementById(cellName).onclick = function () { cellClicked(i) };
}
If you do not "capture" the value in a new scope, the callback will read the value from the actual i-counter.
Do something like this:
for (var i = 0; i < cellCount.length; i++) {
(function(copy_of_i) {
var cellName= "cell"+ i
document.getElementById(cellName).onclick = function () { cellClicked(copy_of_i) };
})(i)
}

Why 'i' passed to a function inside a for loop is equal to a number greater than 'i'? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I have this for loop:
for (var i = 1; i < array.length; i++) {
$('#shop'+i).on('click', function(){ buyThis(i) });
}
The problem is that the i passed as argument to buyThis() isn't equal to the i.
array.length is equal to 3 and #shop1 and #shop2 are created but the argument passed to buyThis() is 3. Why is that?
I'm trying to get an event in which clicking on #shop1 triggers buyThis(1) and clicking on #shop2 triggers buyThis(2).
That's because the code inside the function is called later, when the loop has finished and the variable i has reached its final value.
You can wrap the code that sets the event in an immediately invoked function expression (IIFE) to create a variable for each iteration of the loop:
for (var i = 1; i < array.length; i++) {
(function(i){
$('#shop' + i).on('click', function(){ buyThis(i); });
})(i);
}
This is a scope issue. You need to create a proper closure
for (var i = 1; i < array.length; i++) {
(function(index){
$('#shop'+index).on('click', function(){ buyThis(index) });
})(i);
}
The reason it was different before is because in javascript. the variable is still visible to the handler and by the time it is accessed, it is set to the latest iteration.
This is an issue with block scoping, you can use a closure to solve this
for (var i = 1; i < array.length; i++) {
(function(index){
$('#shop'+index).on('click', function(){ buyThis(index) });
})(i);
}

Categories

Resources