前置知识
setTimeout(function,ms)
接受两个参数,第一个是回调函数,第二个是推迟执行的毫秒数
setTimeout()运行机制
必须要等到当前脚本的同步任务和“任务队列”中已有的事件 全部处理完以后,才会执行setTimeout()指定的任务
setTimeout(function,0)含义
运行下面代码,func1和func2谁会先执行?很明显func2先执行:
setTimeout(function () {
func1(); }, 0)
func2();
- setTimeout(f,0)将第二个参数设为0,作用是让f在现有的任务(脚本的同步任务和“任务队列”中已有的事件)一结束就立刻执行。也就是说,setTimeout(f,0)的作用是,尽可能早地执行指定的任务
- setTimeout(f,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在”任务队列”的尾部添加一个事件,因此要等到同步任务和”任务队列”现有的事件都处理完,才会得到执行。
为什么如下代码会打印 6 个 6
let i = 0
for(i = 0; i<6; i++){
setTimeout(() => {
console.log(i)
},0)
} //6个6
逻辑是:
- 加了setTimeout()函数之后setTimeout会等到当前代码的for循环执行完了,再去执行console.log(i)
而for循环执行完之后,i已经是6了所以会打印出6个6
- 因为只有一个 i , i 不小于 6 的时候才会退出循环,所以循环了6次,得到了6个6
完整解释如下:
for 循环为同步执行,而 setTimeout 为异步执行,遇到上图同步异步混合的情况,会先从上往下执行同步代码,碰到异步的代码会将其插入到任务队列当中等待。 只有当for 循环任务同步执行完,才会执行任务队列里的任务 。也就是说等到 for 循环全部运行完毕后,才会执行 setTimeout ,执行 setTimeout 时需要从当前作用域内寻找一个变量 i ,此时for 循环已执行完毕,当前 i =6,所以执行 setTimeout 时输出为6,任务队列中的剩余5个 setTimeout 也依次执行,输出为6。
解决——for 和 let 配合有奇效 (面试考)
for (let i = 0;i<6;i++) {
setTimeout(() => {
console.log(i)
},0)
} //0、1、2、3、4、5
逻辑是:
- for循环里声明变量的话,每次循环一次就创建一个i
- 因为循环6次,创建了6个 i ,故 i 被分别赋值
关于setitmeout的通俗理解
你正在打游戏,还剩下最后一关,这时候你妈妈让你去吃饭,你嘴上说马上(对应setTimeout(function, 0)),但其实会把游戏打完之后再去吃饭
还可以使用结合const声明
let i
for(i = 0; i<6; i++){
const x = i //在循环体中用const声明
setTimeout(()=>{
console.log(x)
})
} // 0 、1 、2 、3 、4 、5
注意
let 和const声明 都是作用在块内 { }
const 声明的同时必须赋值——区别于let声明