JS是一个单线程程序的解释器,setTimeout本质是隔多长时间将任务添加到任务队列中。
//输出5,5,5,5
for (var i = 1; i < 5; i++) {
setTimeout(function timer() {
console.log(i);
}, 1000);
}
由于JS的只有函数作用域,所以当1秒之后,所有的函数的内部变量都指向了全局变量i
,而此时i
已经变为了5。
知道原因就知道如何解决。我们只需要将i
“变为”一个局部变量。
1:既然只有函数才有作用域,那就生成一个函数。
for (var i = 1; i < 5; i++) {
(function(i){
setTimeout(function timer() {
console.log(i);
}, 1000);
})(i)
}
用立即执行函数来生成作用域,将每个i
传入此匿名函数中。
2:使用ES6的let
来声明变量:
for (let i = 1; i < 5; i++) {
setTimeout(function timer() {
console.log(i);
}, 1000);
}
let相当于在每个块级作用域中都声明了一个变量。
3:使用setTimeout的第三个参数。
一直都忽略了第三个参数,或者说其他参数,他会将第三个参数开始的其他参数都当做第一个函数的参数,参考
我们可以定义每次传入的参数:
for (var i = 1; i < 5; i++) {
setTimeout(function timer(i) {
console.log(i);
}, 1000, i);
}