0

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).

Cress
  • 434
  • 7
  • 23
  • 3
    Another idea would be to stop using `id`s and use classes instead. That way you would have a single handler for all of them. PS: for some reason I think you have an [off-by-one error](https://en.wikipedia.org/wiki/Off-by-one_error) in your code. – zerkms Aug 11 '15 at 21:41

3 Answers3

4

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);
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
1

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.

AmmarCSE
  • 30,079
  • 5
  • 45
  • 53
1

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);
}
blackmind
  • 1,286
  • 14
  • 27