##问题情况
今天遇到了setTimeout在循环中使用最后一个参数执行多次的情况,后发现将setTimeout相关逻辑写在外部方法中,再调用即可解决问题。
##举例说明
for (var i = 0; i < 5; i++) {
console.log("start");
setTimeout(function () {
console.log(i);
},1000)
}
将setTImeout直接写在for循环中,执行会发现“5”被打印了5次,而不是先后打印0,1,2,3,4。这是因为JS是单线程的,循环五次结束后第一次的setTimeout仍没有执行,且当执行setTimeout时使用的参数将是i最后的值5,而不是循环中的参数。
##解决方案
- 直接封装在匿名函数中。
for (var i = 0; i < 5; i++) {
console.log("start");
(function (i) {
setTimeout(function () {
console.log(i);
}, 1000 * i);
})(i);
}
- 把setTimeout写在外部函数中,for循环调用函数。
for (var i = 0; i < 5; i++) {
sleep(i);
}
function sleep(i){
setTimeout(function(){
console.log(i);
},1000 * i);
}
两种写法是相同原理,都是将for循环中的参数传入到方法体中变成内部参数,当循环执行时参数会被保留在代码块中,而不是跟随循环改变,这样setTimeout执行时就能打印实际的参数。注意时间要用1000*i ,这样setTimeout才会根据时间间隔执行。
原理参考文章:https://blog.csdn.net/qq_17627195/article/details/112376567