一个函数的调用时机不同,得到的结果就不同。
先来看这样一段代码:
let i=0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
//打印出6个6
以上代码为什么会打印出六个6而不是0,1,2,3,4,5,呢?
因为setTimeout是异步执行,每一次for循环的时候,setTimeout都执行一次,但是console.log(i)没有被执行,而是被放到了任务队列里,等待执行。
只有主线上的任务执行完,才会执行任务队列里的任务。也就是说它会等到for循环全部运行完毕后,才会执行console.log(i),但是当for循环结束后此时i的值已经变成了6,因此虽然定时器执行了6次,控制台上的内容依然是6。
让上面代码打印 0、1、2、3、4、5 的方法:
for(let i=0;i<6;i++){
setTimeout(()=>{
console.log(i)
},0)
}
//打印出0 1 2 3 4 5
在for和let一起使用的时候,运行环境中 i 的值是每一个循环时创建的 i,所以得到了0-5的值。
除了使用 for let 配合,可以打印出 0、1、2、3、4、5的其他方法:
- 立即执行函数
用立即执行函数给每一个 i 创造一个独立作用域,在立即执行函数执行的时候,i 的值被赋值给ii
for (var i=0; i<6; i++) {
(function(ii) {
setTimeout( ()=> {
console.log(ii);
}, 0 );
})(i);
}
- 拆分结构
还可以将setTimeout的定义和调用分别放到不同部分:
function timer(i) {
setTimeout( console.log( i ), 0 );
}
for (var i=0; i<6;i++) {
timer(i);
}