JavaScript variable scope and event handler

See jsfiddle: http://jsfiddle.net/LsNCa/2/

function MyFunc() { for (var i = 0; i < 2; i++) { // i= 0, 1 var myDiv = $('<div>'); myDiv.click(function(e) { alert(i); // both the two divs alert "2", not 0 and 1 as I expected }); $('body').append(myDiv); } } var myFunc = new MyFunc(); 

I want divs to warn β€œ0” and β€œ1” respectively when I click on them. But both of them warn "2".

When I press the div and the event fires, how and where does the handler find the value of the variable i?

I know that adding closure accomplishes my goal. But why?

+7
javascript scope javascript-events event-handling
source share
4 answers
  function MyFunc() { for (var i = 0; i < 2; i++) { // i= 0, 1 (function(j) { var myDiv = $('<div>'); myDiv.click(function(e) { alert(j); }); $('body').append(myDiv); })(i); } } var myFunc = new MyFunc(); 

The above code is how you work it correctly. Without closing, you will always be the last value of i. We do this to send me to close and let runtime "remember" the meaning of this moment.

+7
source share

You need to close because all your event handlers refer to the same variable i . The for loop updates this, and when the loop executes, the variable contains 2 . Then, when someone clicks on one of the DIV, he accesses this variable.

To solve this problem, each event handler must be a closure with its own variable i , which contains a snapshot of the value during the creation of the closure.

+2
source share

I suggest you read this article

JavaScript Upgrade Ads. This means that both var statements and function declarations will be moved to the beginning of their nesting scope.

As @Barmar said in his answer above, the variable i referenced by both event handlers.

You should avoid declaring functions inside loops. Below is the code that does what you need.

I assume you are using jQuery.

 function MyFunc() { for (var i = 0; i < 2; i++) { // i= 0, 1 var myDiv = $('<div>'); $('body').append(myDiv); } $('div').on('click', function() { alert($(this).index()); }); } var myFunc = new MyFunc(); 
+1
source share

The alert () call occurs after the for-loop completes, which means that the value of "i" will be the last value for anything after that. To fix individual values ​​of "i", you must create a closure for each value by creating a new function:

 function MyFunc() { function alertFn(val) { return function () { alert(val); }; } for (var i = 0; i < 2; i++) { var myDiv = $('<div>'); myDiv.click(alertFn(i)); $('body').append(myDiv); } } var myFunc = new MyFunc(); 

Closing captures the value of "i" at the time of its transfer to the function, allowing alert () to show the expected value.

0
source share

All Articles