JQuery.each() and closures
Long question, but bear with me. Jquery.each() seems to behave differently than expected regarding closures. For instance, if I want each row in a table to print out it's inner HTML inside an alert box when I click on it, I could use the following code and html.
HTML:
- <html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
$(document).ready( function() {
});
</script>
</head>
<body>
<table>
<tr><td>Row 1</td></tr>
<tr><td>Row 2</td></tr>
<tr><td>Row 3</td></tr>
</table>
</body>
</html>
The following snippet incorrectly prints out the final row's inner HTML when placed in the document.ready function, no matter which row you click on. I'm assuming this is do to the closure making the value variable exist in scope as long as the onClick handler.
- /* Bad example */
// Attach a click handler to print it's inner html
var nodes = document.getElementsByTagName( 'tr' );
for( var i = 0; i < nodes.length; i++ )
{
var value = nodes[i].innerHTML;
nodes[i].onclick = function( e ) {
alert( value );
}
}
This snippet works as expected (thanks to Javascript - The Good Parts):
- /* Good function */
// Attach a click handler to print it's inner html
var nodes = document.getElementsByTagName( 'tr' );
for( var i = 0; i < nodes.length; i++ )
{
var value = nodes[i].innerHTML;
nodes[i].onclick = function( value ) {
return function(e){
alert( value );
}
}(value);
}
The Jquery.each() statement I have looks like this:
- /* Jquery */
// Attach a click handler to each tr that alerts it's index in the table
$("tr").each(
function() {
var value = this.innerHTML;
$(this).bind( 'click', function() { alert( value ); } );
}
);
This script seems like it should work exactly the first bad snippet, except that it works like the second good snippet. Shouldn't the value() parameter now be set for as long as the onClick handlers? How does the .each() function set the onClick handlers to use the value that exists when ever the onClick handler is set? Can I always count on this behavior, or am I missing something?
Thanks,
Gary