1

Possible Duplicate:
How do JavaScript closures work?

I am trying to use the value of a loop counter inside another function inside the loop. I know this is related to function closures. Its getting a little confusing. I figure if someone can explain on this problem, I'd understand.

for (var i = 0; i < foo.length; i++) {
    // $('<li/>').addClass('box').append($('<img/>').attr({'src':foo[i].image, 'data-phrase':foo[i].phrase}).hide()).appendTo($('ul.boxPack'))
    $('<li/>').addClass('box')
              .attr('data-phrase', foo[i].phrase)
              .bind('click', function (i) {
                   alert(i);
                   console.log(foo[2]);
                   $(this).append($('<img/>').attr('src', foo[2].image))
               })
              .appendTo($('ul.boxPack'));
}

I am unable to alert i.

Community
  • 1
  • 1
amit
  • 10,133
  • 22
  • 72
  • 121
  • The specific inability to alert `i` comes from the fact that you defined a parameter to the `click` handler as `i`. Therefore, you'll be alerting the event object which is passed as the first argument to the handler. – I Hate Lazy Oct 11 '12 at 19:11
  • The general inability to alert the expected value of `i` *(once the above is fixed)* will stem from the fact that a `for` statement *does not create variable scope*. Only a function call creates scope. That means that if you want each handler created in the loop to reference the value of `i` that existed at each iteration, you would need to create the handler inside a function that has its own `i` variable. There are different patterns used to accomplish this. – I Hate Lazy Oct 11 '12 at 19:14
  • But if what you're ultimately after is the `data-phrase` attribute, you'd just use `$(this).attr('data-phrase')` or `thsi.getAttribute('data-phrase')` to fetch it from the element in the handler. Or in modern browsers, `this.dataset.phrase`. – I Hate Lazy Oct 11 '12 at 19:16
  • Getting back to the value of `i`, if you use a functional style iterator, like `.forEach()` or jQuery's `$.each()` to do the loop, you'll have the function invocation you need to retain `i`. So therefore you could simply replace the `for` statement with `$.each(foo, function(i, item) {...});`, and your handlers will reference the local `i` variable inside the function *(since the function is invoked once per iteration of `foo`)*. – I Hate Lazy Oct 11 '12 at 19:19

0 Answers0