好吧,第一个堆栈溢出问题。我希望我做对了。
我正在尝试运行以下代码:
for(var i = 1; i < 17; i++){
console.log("for loop runs. i is " + i);
setTimeout(function(){
console.log("setTimeout runs. i is " + i);
if(i < 3){
$( ".example1" ).append( i );
$( ".example2" ).append( i );
$( ".example3" ).append( i );
$( ".example4" ).append( i );
$( ".example5" ).append( i );
}
else if(i<5){
$( ".example1" ).append( i );
$( ".example2" ).append( i );
$( ".example3" ).append( i );
$( ".example5" ).append( i );
}
else if(i<11){
$( ".example1" ).append( i );
$( ".example2" ).append( i );
$( ".example3" ).append( i );
}
else if(i<15){
$( ".example1" ).append( i );
$( ".example3" ).append( i );
}
else if(i<17){
$( ".example1" ).append( i );
}
},200);
} //end for loop
我在控制台中得到以下输出:
for loop runs. i is 2
for loop runs. i is 3
for loop runs. i is 4
for loop runs. i is 5
for loop runs. i is 6
for loop runs. i is 7
for loop runs. i is 8
for loop runs. i is 9
for loop runs. i is 10
for loop runs. i is 11
for loop runs. i is 12
for loop runs. i is 13
for loop runs. i is 14
for loop runs. i is 15
for loop runs. i is 16
(16) setTimeout runs. i is 17 // <---- runs 16 times
因此,for
循环运行并递增到17,然后setTimeout
运行16次。我不明白这里发生了什么。
解决方案:setTimeout
执行时变量没有期望值
变量关闭问题。IIFE进行救援:
for(var i = 1; i < 17; i++){
console.log("for loop runs. i is " + i);
(function (ii) {
setTimeout(function(){
console.log("setTimeout runs. ii is " + ii);
// the rest of your code goes here
},200);
}(i));
}
解释:
之所以要获取值“ 17”,i
是因为在setTimeout
执行s时,i
在for
循环的最后一次迭代中为其分配了值“ 17” 。(i
必须将其设置为“ 17”,循环才能终止。)当您处理i
该setTimeout
函数时,将为其提供引用i
,而不是的当前值i
。
变量作用域由在函数var
执行时和执行时被实例化的函数('d)确定。i
是var
在准备for
循环时自动(自动)完成的。那么,for
循环存在于什么“功能”中呢?window
,或全球范围。那是范围i
。那就是setTimeout
去获取i
何时触发的价值。
因此,要解决该问题,我们需要在函数中实例化一个变量并执行该函数以在程序执行的那一刻锁定该变量的值。
从概念上讲,首先,编写一个具有一个或多个参数的函数:
function (x, y, z) {
// stuff here
};
x
,,y
并z
在执行此函数时在此函数范围内获取var'd。
其次,执行功能,并传递必要的参数:
function (x, y, z) {
// stuff here
}(a, b, c);
a
,b
和c
可能已经在全局范围内更改了,现在您要将它们的当前值作为参数传递给此函数。
第三,将函数包装在括号中,以便JavaScript解释器将其视为函数表达式而不是函数声明。
(function (x, y, z) {
// stuff here
}(a, b, c));
顺便说一句,这也有效:
!function (x, y, z) {
// stuff here
}(a, b, c);
...一样~
,+
和-
。您只需要在行的开头添加一些良性运算符,即可将JS甩出函数声明狂热的状态。
就像for
循环一样,函数参数变量在var
执行函数时会自动生成,但是在这种情况下,作用域在此函数本身之内。因此,价值的i
在执行该行代码瞬间被传递给新变量ii
的IIFE函数内部,并锁定在该函数范围内。现在,当setTimeout
最终准备好执行时,它会寻找该功能范围而不是全局范围来获取值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句