- A+
在开始之前先看个面试例子
为什么会是0 1 2 2,而不是 0 0 1 1
再来看个例子
输出结果是4个undefined,为何不是1,2,3,4?
这是为什么呢,这是因为setTimeout是异步的,运行机制是指定的代码,必须等到本次执行的所有同步代码都执行完,才会执行。优先关系:异步任务要挂起,先执行同步任务,同步任务执行完毕才会响应异步任务。
这里解释下异步执行过程,浏览器有个定时器(timer)模块,定时器到了执行时间才会把异步任务放到异步队列,for循环体执行的过程中并没有把setTimeout放到异步队列中,只是交给定时器模块了。4个循环体执行速度非常快(不到1毫秒)。定时器(即使设置了0默认也是4毫秒)到了设置的时间才会把setTimeout语句放到异步队列中。
看张图:
先来说说第一个例子:for循环结束时候此时j = 2,浏览器定时器模块中的setTimeout交给了任务队列后输出,所以就有了0=》1=》2=》2
再来说说第二个例子:也是同样的道理,messages执行了四次,然后for循环结束,此时i=4,因为messages[4]没有值为undefined,最大为3,所有是4个undefined
最后说说例二解决方法
方法一:
使用let,不要用var,因为let是有作用域的,所以settimeout的i值指向的是每个循环体中的i值,每次循环的值都是不一样的,打印出来的是最终输出1,2,3,4
方法二(闭包):
这个就很好理解了,因为每个i的值都会传入function中,settimeout中的i作用域在这个闭包中,每次指向的是闭包中的i,所以打印出来的值1,2,3,4
总结:setTimeout是异步函数,异步任务要挂起,先执行同步任务,同步任务执行完毕才会响应异步任务