我有这个脚本:
for (var i = 1; i <= 2; i++) {
setTimeout(function() { alert(i) }, 100);
}
But 3
两次都会收到警报,而不是1
then 2
.
有没有办法通过i
,而不将函数写为字符串?
您必须为每个超时函数安排一个不同的“i”副本。
function doSetTimeout(i) {
setTimeout(function() {
alert(i);
}, 100);
}
for (var i = 1; i <= 2; ++i)
doSetTimeout(i);
如果您不这样做(并且同一想法还有其他变体),那么每个计时器处理程序函数都会share相同的变量“i”。循环结束后,“i”的值是多少?是 3!通过使用中介函数,copy变量的值被确定。由于超时处理程序是在该副本的上下文中创建的,因此它有自己的私有“i”可供使用。
Edit:
随着时间的推移,出现了一些评论,其中明显存在一些混乱,因为设置一些超时会导致处理程序同时触发。重要的是要理解这个过程配置计时器 — 调用setTimeout()
——几乎不花时间。也就是说,告诉系统“请在 1000 毫秒后调用此函数”几乎会立即返回,因为在计时器队列中安装超时请求的过程非常快。
因此,如果一个演替发出了超时请求,就像OP中的代码和我的答案中的情况一样,并且每个请求的时间延迟值都是相同的,那么一旦经过该时间量,所有计时器处理程序将在之后被调用另一个快速连续。
如果您需要定期调用处理程序,您可以使用setInterval()
,这被称为完全一样setTimeout()
但在重复延迟请求的数量后,它将多次触发,或者您可以建立超时并将时间值乘以迭代计数器。即修改我的示例代码:
function doScaledTimeout(i) {
setTimeout(function() {
alert(I);
}, i * 5000);
}
(With a 100
毫秒超时,效果不会很明显,所以我把这个数字提高到5000。)的值i
乘以基本延迟值,因此在循环中调用该值 5 次将导致延迟 5 秒、10 秒、15 秒、20 秒和 25 秒。
Update
2018 年,有一个更简单的选择。有了在比函数更窄的范围中声明变量的新功能,如果修改原始代码就可以工作:
for (let i = 1; i <= 2; i++) {
setTimeout(function() {
alert(i)
}, 100);
}
The let
声明,不同于var
,本身就会导致有一个明显的i
对于循环的每次迭代。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)