[英]scope of variables in JavaScript callback functions
我希望下面的代码警告“0”和“1”,但它会两次警告“2”。 我不明白原因。 不知道这是不是jQuery的问题。 另外,如果这些帖子的标题和标签不准确,请帮我编辑标题和标签。
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
for (var i=0; i<2; i++) {
$.get('http://www.google.com/', function() {
alert(i);
});
}
});
</script>
</head>
<body>
</body>
</html>
您将在所有回调中共享单个i
变量。
因为Javascript闭包通过引用捕获变量,所以回调将始终使用i
的当前值。 因此,当循环执行后jQuery调用回调时, i
将始终为2
。
您需要将i
作为参数引用到单独的函数中。
例如:
function sendRequest(i) {
$.get('http://www.google.com/', function() {
alert(i);
});
}
for (var i = 0; i < 2; i++) {
sendRequest(i);
}
这样,每个回调都将有一个单独的闭包,带有一个单独的i
参数。
替代SLaks的回答
$(function() {
for (var i=0; i<2; i++) {
$.get('http://www.google.com/', function(i) {
return function() { alert(i); }
}(i));
}
});
另一种解决方案是使用你的回调并逐字地使它成为一个命名函数。
我为什么要这样做?
如果一个函数正在做一个变量需要占用新范围的东西,那么匿名函数很可能需要突破一个新函数。 这还将确保不必通过复制变量或包装回调来为代码引入额外的复杂性。 你的代码将保持简单和自我描述。
例:
function getGoogleAndAlertIfSuccess(attemptNumber) {
$.get('http://www.google.com/', function() {
alert(attemptNumber);
});
}
function testGoogle() {
for (var i=0; i<2; i++) {
getGoogleAndAlertIfSuccess(i);
}
}
这里发生的是你的AJAX请求$.get
在循环完成后完成。 因此, i
最终成为迭代完成时设置的最终变量,为2.这只是一个奇怪的JavaScript陷阱,与jQuery无关。
您可以做的一件事是异步排队这些调用,以便迭代停止,直到当前的AJAX请求完成。 如果您不想这样做,可以在每次迭代中捕获function
闭包中的变量i
。
像这样的东西:
for ( var i = 0; i < 2; i++ )
(function(iter){
$.get('http://www.google.com/', function(){
alert( iter );
});
})(i); // Capture i
看来你已经在循环中创建了一个闭包Mozilla Developers Reference有一个很好的部分 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.