首先,来看下以下代码的执行结果:
var arr = [1,2,3,4,5]
for(var i= 0;i< arr.length; i++){
setTimeout(function(){
console.log(i)
},100)
}
很明显,这个循环我们是想得到 0,1,2,3,4 的结果,但是最后会打印出5个5,这是因为JavaScript会将异步任务放在一个队列里面,等所有的同步任务执行完成之后才会执行异步任务。所以在以上代码中遇到异步任务setTimeout后继续执行for循环,由于只有一个全局作用域,每次 for 循环修改的都是同一个i,等for循环执行完毕即 i 等于5时,开始执行异步任务setTimeout,打印此时 i 的值 5 。那么,要怎么解决这个问题呢。
1.使用es6新增的 let 来声明变量,let可以声明一个块级作用域,在每个块级作用域里面的 i 都是属于该作用域的,即每个作用域都有它自己的 i,所以可以得到想要的结果。
var arr = [1,2,3,4,5]
for(let i= 0;i< arr.length; i++){
setTimeout(function(){
console.log(i) //0,1,2,3,4
},100)
}
2.使用自调用函数。将 i 作为函数的参数传递进去,函数执行有自己的函数作用域,也可以达到效果。
var arr = [1,2,3,4,5]
for(var i= 0;i< arr.length; i++){
(function(i){
setTimeout(function(){
console.log(i) //0,1,2,3,4
},100)
})(i)
}