问题
I have the following JS:
for ( var i = 1; i <= 2; i++ ) {
$(window).load(function() {
alert(i);
});
}
When the page loads, it gives me an alert twice as expected. But the strange thing is the value of i is 3 on both alert. I expect the value of i is 1 on the first alert and 2 on the second alert. What causes the problem? Thank you in advance!
UPDATE #1
What if I need to place the function inside the loop because I want to use number increment as selector? Is there a solution to this problem? Here is what I mean
for ( var i = 1; i <= 2; i++ ) {
$( '.element-' + i + ' .span' ).click( function( event ) {
$( '.element-' + i + ' ul' ).show( 'fast' );
});
}
The click function is not fired because we already know that i = 3. I want the click function get fired when .element-1 .span and .element-2 .span is clicked. Is there a workaround?
回答1:
You are creating a closure with captured variable i. When window.load event handlers execute, the loop has had completed and the value of this variable is 3.
for ( var i = 1; i <= 2; i++ ) {
$(window).load((function(iter) {
return function() { alert(iter); };
})(i));
}
Update:
In your code, you are directly assigning an anonymous function to be an event handler for $(window).load. This function binds loop iterator variable i - as a variable, and, when this function executes, the value of i is what was assigned by all previously executed code, which is the completed loop - terminated when i became 3.
My code can be rewritten:
function getEventHandler(iter) {
return function() { alert(iter); };
}
for ( var i = 1; i <= 2; i++ ) {
$(window).load(getEventHandler(i));
}
getEventHandler returns a function (which becomes $(window).load event handler). That returned function binds iter parameter with the value this parameter has when getEventHandler executes - every time it executes. In the loop we call getEventHandler immediately in each loop iteration with the current (changing) values of i.
回答2:
I assume that what you actually want to do is have the for loop inside the $(window).load function like so:
$(window).load(function() {
for (var i = 0; i <= 2; i++) {
alert(i);
}
});
This will run the for loop after the window is loaded.
Explanation for why you are getting 3 in your alerts
The reason you are getting 3 in your alerts currently is illustrated by this diagram:
TIME
| The for loop is begun (a = 0)
| The load event on the window is handled by the specified function the load
| function itself does not run
| i is incremented (i++) now i = 1
| The load event on the window is handled again
| i is incremented (i++) now i = 2
| The load event on the window is handled again
| i is incremented (i++) now i = 3
| The condition of the for loop fails so execution is discontinued
|
| The window is loaded
| Each of the callbacks is run and at this point i = 3 so 3 is alerted each
| time
来源:https://stackoverflow.com/questions/28756691/javascript-for-loop-increment-behaves-strangely