0

I am trying to pass I into the inputItems[i].on so i can set it to do a specific task (defined by createSelectedInputItem(i)), how do you pass the variable i into the function() { ..operation here }?

for(var i=0; i< 6; i++){
    console.log("setting mouse event for : " + i);

    // Bring in all the input items
    inputItems[i].on('click', function() {

      console.log("i is still:" + i );
      input.tween.reverse();
      console.log("pressed" + i);
      createSelectedInputItem(i);

      for(var j=0; j< 6; j++){
        inputItems[j].tween.reverse();
      } 
    });
  }

LOG

//When the page is loaded

setting mouse event for : 0

setting mouse event for : 1 

setting mouse event for : 2 

setting mouse event for : 3 

setting mouse event for : 4 

setting mouse event for : 5 

//When pressing one of the inputItems

i is still:6

pressed6 

this isnt even suppose to exist

karthikr
  • 97,368
  • 26
  • 197
  • 188
Daryl Rodrigo
  • 1,387
  • 2
  • 11
  • 19
  • possible duplicate of: http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – Mike Edwards Oct 30 '13 at 18:29

2 Answers2

0
inputItems[i].on('click', function() {
    // By the time this runs, any variable outside its scope may change,
    // which in this case is 'i' which runs in a loop.
});

You should capture the i by wrapping it like this:

(function(i) {
    inputItems[i].on('click', function() {
        // Now i is an argument to the wrapping closure
        console.log(i);
    });
})(i);
lxe
  • 7,051
  • 2
  • 20
  • 32
0

The problem you are facing is that of closures, which are a slightly non-intuitive aspect of Javascript's scoping.

Consider how many variables you have there. How many times does the variable i exist? The answer is "as many times as there are scopes that define i". In this case, that means there is only one variable i, which is referred to throughout your code.

You do a loop with i:

for(var i=0; i< 6; i++){

After this loop has completed (which happen before you do any clicks), i is 6. It will never change again, and it will never refer to any other number.

So the click handler fires, and this line of code is run:

console.log("i is still:" + i );

i is the same variable, and it will therefore be the value 6.

The way around this is to introduce a new variable for each iteration of the loop.

for (var i = 0; i < 6; i++) {
    (function (innerI) { // create a function with an argument called innerI
        console.log("setting mouse event for : " + i);

        // Bring in all the input items
        inputItems[innerI].on('click', function () {
            console.log("i is still:" + i);
            console.log("innerI is: " + innerI);
            input.tween.reverse();
            console.log("pressed" + innerI);
            createSelectedInputItem(i);

            for (var j = 0; j < 6; j++) {
                inputItems[j].tween.reverse();
            }
        });
    }(i)); // invoke the function with i as the argument
}

In this code, we create an anonymous function. The function takes one argument, innerI. We then immediately invoke that function, and pass i as the argument. This creates a new scope and a new variable, so it is not changed when i++ happens at the end of the loop.

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
  • Ahh this makes so much such, the fact that nothing can change the innerI variable is what makes it work. THANKS :D – Daryl Rodrigo Oct 30 '13 at 18:41
  • @DarylRodrigo Note that my code is practically the same as Ixe's, except that mine calls the new variable `innerI` rather than `i`. Both are valid, but I find it confusing to have multiple variables with the same name in nested scopes. – lonesomeday Oct 30 '13 at 18:43