循环中的javascript var声明

Car*_*uro 8 javascript variables scope

/*Test scope problem*/
for(var i=1; i<3; i++){
    //declare variables
    var no = i;
    //verify no
    alert('setting '+no);

    //timeout to recheck 
    setTimeout(function(){
        alert('test '+no);
    }, 500);
}
Run Code Online (Sandbox Code Playgroud)

它按预期警告"设置1"和"设置2",但在超时后它输出"测试2"两次 - 由于某种原因,变量"否"在第一次循环后没有重置......

我发现只有一个"丑陋"的解决方法:

/*Test scope problem*/
var func=function(no){
    //verify no
    alert('setting '+no);

    //timeout to recheck 
    setTimeout(function(){
        alert('test '+no);
    }, 500);
}
for(var i=1; i<3; i++){
    func(i);
}
Run Code Online (Sandbox Code Playgroud)

有关如何以更直接的方式解决此问题的任何想法?或者这是唯一的方法吗?

Tim*_*own 13

JavaScript没有块范围,并且提升了变量声明.这些事实共同意味着您的代码相当于:

var no;

/*Test scope problem*/
for(var i=1; i<3; i++){
    //declare variables
    no = i;
    //verify no
    alert('setting '+no);

    //timeout to recheck 
    setTimeout(function(){
        alert('test '+no);
    }, 500);
}
Run Code Online (Sandbox Code Playgroud)

当你的超时函数执行时,循环结束很长时间,并no保持其最终值为2.

解决这个问题的方法是将当前值传递给no一个函数,该函数为每次调用创建一个新的回调setTimeout.每次创建一个新函数意味着每个setTimeout回调都绑定到具有自己的变量集的不同执行上下文.

var no;

/*Test scope problem*/
for(var i=1; i<3; i++){
    //declare variables
    no = i;
    //verify no
    alert('setting '+no);

    //timeout to recheck 
    setTimeout( (function(num) {
            return function() {
                alert('test '+num);
            };
        })(no), 500);
}
Run Code Online (Sandbox Code Playgroud)