0

Possible Duplicate:
Javascript: closure of loop?

I have following code inside javascript:

for (var i=0; i < images_array.length; i++) {
$('#thumb_'+ i).live('click', function(){
    $('#image_container_' + current_image_index).hide();
    current_image_index = i;
    alert(current_image_index);
    $('#image_container_' + current_image_index).show();
});}

when I click on any thumb, i get images_array.length value. Does anyone know what is happenning?

Community
  • 1
  • 1
user1801180
  • 125
  • 1
  • 1
  • 5
  • 1
    Your `i` variable is stored in a local closure. You need to add another level of function that has a local copy of `i`. – Scott Sauyet Dec 04 '12 at 01:44
  • this has been answered so countless times on SO, Y U NO SEARCH – jAndy Dec 04 '12 at 01:45
  • 1
    I'm afraid that this is only easy to search for once you understand the solution. Without understanding the idea of closures, it would be hard to have any idea what to search on... – Scott Sauyet Dec 04 '12 at 01:51
  • @ScottSauyet: I disagree. Search for "javascript loop function" or anything similar containing the word "loop". – jAndy Dec 04 '12 at 02:02
  • 1
    @jAndy: But why is `loop` *a priori* any more salient than `image`, `live`, `click`, or `array`? Or even `length`, `current`, `hide`, or `show`, which at least appear in the code snippet, which `loop` doesn't. – Scott Sauyet Dec 04 '12 at 02:07

2 Answers2

1

You need to create a closure for the click handler function, like this:

for (var i=0; i < images_array.length; i++) {
    $('#thumb_'+ i).live('click', 
        (function(i) {
            return function(){
                $('#image_container_' + current_image_index).hide();
                current_image_index = i;
                alert(current_image_index);
                $('#image_container_' + current_image_index).show();
            }
        })(i)
    );
}

The problem is that, without the closure, the variable is shared across every handler function -- it continues getting updated, which is why every handler ends up getting the array.length value. Using the closure creates a locally-scoped copy of the variable i.

Here's a demo that shows the difference:

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
0
$.each(images_array,function(value,i) {
  $('#thumb_'+ i).live('click', function(){
  $('#image_container_' + current_image_index).hide();
  current_image_index = i;
  alert(current_image_index);
  $('#image_container_' + current_image_index).show();
});}

As others have said, you need a closure. Now, you're already using jQuery so forget about for() and directly use $.each.

Christophe
  • 27,383
  • 28
  • 97
  • 140