Resolve scoping issues in jQuery with anonymous functions

Posted on May 21, 2011

I had a bit of a head-scratching moment recently when I was using jQuery to bind event handlers to elements in a loop. Usually I would just use jQuery’s .each() method but in this specific case that wasn’t an option. Consider the following (simplified) code:

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul>
	<li id="item-1">Item 1</li>
	<li id="item-2">Item 2</li>
	<li id="item-3">Item 3</li>
</ul>
 
<script type="text/javascript">
	for ( var i = 1; i <= 3; i ++ ) {
		$('#item-' + i).click(function() {
			alert('You clicked item ' + i);
		});
	}
</script>

Against my intuition, clicking any of the three li elements would return return “You clicked item 4”. I then realized that i was being read after the for-loop had finished. To solve this, wrap the function in another anonymous function passing i as an argument:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul>
	<li id="item-1">Item 1</li>
	<li id="item-2">Item 2</li>
	<li id="item-3">Item 3</li>
</ul>
 
<script type="text/javascript">
	for ( var i = 1; i <= 3; i ++ ) {
		(function(i) {
			$('#item-' + i).click(function() {
				alert('You clicked item ' + i);
			});
		}(i));
	}
</script>

This way the second i lives in the same scope as the alert() function which will now return the correct value.

Scroll to top

Comments

(None yet)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Fork me on GitHub