shenkwen
shenkwen

Reputation: 3880

Need explanation on jQuery Event.data example

My question is about the example on this page: http://api.jquery.com/event.data/

<button> 0 </button>
<button> 1 </button>
<button> 2 </button>
<button> 3 </button>
<button> 4 </button>

<div id="log"></div>

JS:

var logDiv = $( "#log" );

for ( var i = 0; i < 5; i++ ) {
  $( "button" ).eq( i ).on( "click", { value: i }, function( event ) {
    var msgs = [
      "button = " + $( this ).index(),
      "event.data.value = " + event.data.value,
      "i = " + i
    ];
    logDiv.append( msgs.join( ", " ) + "<br>" );
  });
}

In this demo, when I click one of the buttons, the output is like the following:

button = 0, event.data.value = 0, i = 5

what I don't understand is why "i = 5" here, shouldn't "i" be equal to "0" in this case?

Upvotes: 0

Views: 136

Answers (3)

Blazemonger
Blazemonger

Reputation: 92933

That's the point. When the code is run, five different event handlers are set. Here's what the first event handler looks like from the JS engine's point of view:

$("button").eq(0).on("click", {value: 0}, function(event) { /* i set to zero */
    var msgs = [
      "button = " + $(this).index(),
      "event.data.value = " + event.data.value, /* passed in via {value: 0} */
      "i = " + i /* i remains a variable inside the callback function */
    ];
    logDiv.append( msgs.join( ", " ) + "<br>" );
  });

Note that i isn't set to zero inside the callback function; it remains a variable. And at the time that event handler is called (when the button is clicked), the for loop is complete and i=5.


To do what you imagine should take place, we'd need to wrap the inside of the loop in a closure:

for (var i = 0; i < 5; i++) {
    (function (i) { /* start of closure */
        $("button").eq(i).on("click", function (event) {
            var msgs = [
                "button = " + $(this).index(),
                "i = " + i];
            logDiv.append(msgs.join(", ") + "<br>");
        });
    })(i); /* end of closure */
}

http://jsfiddle.net/mblase75/qeXn5/

...or just use event.data.value instead of i.

Upvotes: 0

enriquinho
enriquinho

Reputation: 245

The event listeners hold a reference to the "i" variable, which is used in the for statement. This value will be 5 after the for loop has ended and all the "click" listeners are being added: it is the latest value being set in "i++" before failing the condition "i < 5".

Upvotes: 0

gen_Eric
gen_Eric

Reputation: 227270

This is because the i you are referencing when you do "i = " + i is the same i that's being incremented in the for loop.

When the loop ends, and when your click event is finally triggered, i will have been incremented to 5. When you pass it as event.data, you are "capturing" the current value, so that's why you get 0.

Upvotes: 1

Related Questions