for(var i = 0 ; i < 5 ; i++){
setTimeout(function(){
console.log(i)
},1000)
}
这段代码的输出是连续出现五个5。那怎么才能让他连续打出0-4呢?
打印出五个5的原因
这是因为setTimeout的延迟加载,所谓延迟加载就是指setTimeout先将回调函数放到等待队列中等待区域内其他主程序执行完毕后,按时间顺序先进先出执行回调函数。本质上是作用域的问题。
所谓本质上是作用域问题,在我理解上就是目前根据for循环遍历出五个
setTimeout,每个setTimeout在运行的时候都会将function函数压入队列,但是由
于var声明的变量在全局环境都会被调用,所以在执行压入下一个function的时
候,会改变上一个已经压入队列的function中的变量i,所以最后会打印五个5.
知道了问题的原因,就可以进行修改了。
解决
使用let、闭包、setTimeout第三个参数、拆分结构https://www.cnblogs.com/wl0804/p/11987833.html
其中闭包的方式除了用到了js的闭包还用到了立即执行函数。
下面的解释来:https://www.jianshu.com/p/d9adadcb05f8
立即执行函数,顾名思义,声明一个函数,并立即执行它。
首先我们区分一下函数声明和函数表达式:区分函数声明和函数表达式最简单的方法是看function关键字出现在声明中的位置。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。
所以我们可以用一个()把函数扩起来,让他成为一个函数表达式。然后在用自调用的方式将数据传入function中:
for(var i=0;i<5;i++){
(function(j){
setTimeout(function(){
console.log(j)
},1000)
})(i)
}