首先看一个常见的函数,该函数输出的是什么呢?
对的,就是5个6.
为什么会这样呢?因为setTimeout是个异步函数,每次循环的时候都会创建一个定时器,任务放到队列里,等主线程执行完才会执行定时器,这个时候循环跑完了,最后一次的 i = 5 + 1 = 6,所以输出5个6.
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, 1000 );
}
方法一
方法一使用了let,let是块级作用域变量,在每一次循环都会重新声明i;var则是在for循环之外作用域定义的变量,无法传入这个函数的执行域中。
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, 1000 );
}
方法二
使用了匿名函数,这种写法相当于声明了匿名函数之后立即调用,而且将i以参数形式传入。我们知道函数的参数传递是以值传递的,也就是说会重新copy一个与i相等的值传到匿名函数中,timer则是一个闭包,每次获取的变量都是新的i值,因此可以打印出1,2,3,4,5.
for (var i = 1; i <= 5; i++) {
(function(i){
setTimeout(function timer() {
console.log(i);
}, 1000 );
})(i);
}
方法三
方法三与二差不多道理,也是一个函数传递是以值形式传递,因而每次的i值会不一样。
function printI(i) {
setTimeout( function timer() {
console.log(i);
}, 1000 );}
for (var i = 1; i <= 5; i++) {
printI(i);
}
如有不对的地方敬请指正,谢谢~