循环中的javascript var声明
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环中的javascript var声明相关的知识,希望对你有一定的参考价值。
/*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);
}
它按预期警告“设置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);
}
有关如何以更直接的方式解决此问题的任何想法?或者这是唯一的方法吗?
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);
}
当你的超时函数执行时,循环结束很长时间,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);
}
这与您的修复基本相同,但使用不同的语法来实现范围调整。
/*Test scope problem*/
for (var i = 1; i < 3; i++) {
//declare variables
var no = i;
//verify no
alert('setting ' + no);
//timeout to recheck
(function() {
var n = no;
setTimeout(function() {
alert('test ' + n);
}, 500);
})();
}
Javascript没有词法作用域(for-loop不会创建新的作用域),您的解决方案是标准的解决方法。另一种写这个的方法可能是:
[1, 2].forEach(function(no){
//verify no
alert('setting '+no);
//timeout to recheck
setTimeout(function(){
alert('test '+no);
}, 500);
})
forEach()是在ECMAScript 5中引入的,并且存在于现代浏览器中但不存在于IE中。您可以使用my library来模拟它。
我喜欢我可以从this answer获得如此多的里程数。
如果您需要帮助来应用该答案,请告诉我。
编辑
当然。我们来看看你的原始代码。
//timeout to recheck
setTimeout(function(){
alert('test '+no);
}, 500);
看到那个匿名函数?你传递给setTimeout()
的人?直到定时器这样说才会调用它 - 在循环退出后500ms就好了。
您希望的是no
“就地”进行评估,但不是 - 它在调用函数时进行评估。到那时,no
是2。
为了解决这个问题,我们需要一个在循环迭代期间执行的函数,它本身将返回一个setTimeout()
可以按照我们期望的方式使用的函数。
setTimeout(function( value )
{
// 'value' is closed by the function below
return function()
{
alert('test ' + value );
}
}( no ) // Here's the magic
, 500 );
由于我们创建了匿名函数并立即调用它,因此创建了一个新的作用域,我们可以在其中关闭变量。而且这个范围围绕value
,而不是no
。由于value
为每个循环收到一个新的(咳咳)值,这些lambdas中的每一个都有它自己的值 - 我们想要的那个。
因此,当setTimeout()触发时,它正在执行从闭包函数返回的函数。
我希望能够解释它。
以上是关于循环中的javascript var声明的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript“for-in”循环中的“var”还是没有“var”?