scope of variables in JavaScript callback functions
我希望下面的代码警告"0"和"1",但它会两次警告"2"。 我不明白原因。 不知道这是不是jQuery的问题。 另外,如果这些帖子的标题和标签不准确,请帮我编辑标题和标签。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"> <script type="text/javascript"> $(function() { for (var i=0; i<2; i++) { $.get('http://www.google.com/', function() { alert(i); }); } }); </head> <body> </body> </html> |
您将在所有回调中共享单个
由于Javascript闭包通过引用捕获变量,因此回调将始终使用
您需要将
例如:
1 2 3 4 5 6 7 8 9 | function sendRequest(i) { $.get('http://www.google.com/', function() { alert(i); }); } for (var i = 0; i < 2; i++) { sendRequest(i); } |
这样,每个回调都将有一个单独的闭包,其中包含一个单独的
替代SLaks的回答
1 2 3 4 5 6 7 | $(function() { for (var i=0; i<2; i++) { $.get('http://www.google.com/', function(i) { return function() { alert(i); } }(i)); } }); |
另一种解决方案是使用你的回调并逐字地使它成为一个命名函数。
我为什么要这样做?
如果一个函数正在做一个变量需要占用新范围的东西,那么匿名函数很可能需要突破一个新函数。这还将确保不必通过复制变量或包装回调来为代码引入额外的复杂性。你的代码将保持简单和自我描述。
例:
1 2 3 4 5 6 7 8 9 10 11 | function getGoogleAndAlertIfSuccess(attemptNumber) { $.get('http://www.google.com/', function() { alert(attemptNumber); }); } function testGoogle() { for (var i=0; i<2; i++) { getGoogleAndAlertIfSuccess(i); } } |
这里发生的是你的AJAX请求
您可以做的一件事是异步排队这些调用,以便迭代停止,直到当前的AJAX请求完成。如果您不想这样做,可以在每次迭代中捕获
像这样的东西:
1 2 3 4 5 6 | for ( var i = 0; i < 2; i++ ) (function(iter){ $.get('http://www.google.com/', function(){ alert( iter ); }); })(i); // Capture i |
看来你已经在循环中创建了一个闭包Mozilla Developers Reference有一个很好的部分。