var i = 5;
while(i--){
setTimeout(function(){
console.log(i)
},0)
}
console.log(666)
答案:先执行 666 ,然后输出5个 -1
while(){}
就是一个循环语句,判断小括号内的条件,成立则执行大括号内的语句,否则结束循环。
就是0和非0会被隐式转换为true or false
隐形考点,while小括号内部,会进行隐式转换,将其他类型的值转为Boolean布尔值类型的进行判断
劝你别去试while(-1){console.log("I'm fantastic!")}。因为我刚才就是导致浏览器死机,然后关掉重写的博文【多么痛的领悟】
--i 和 i--
var i = 5;
while(--i){
setTimeout(function(){
console.log(i)
},0)
}
console.log(666)
那么结果就是这样了,输出4个0。
这是因为呢,
【i--】 这里的顺序,是先输出i,再执行i=i -1;
【--i】只是先做i=i -1;然后输出i;
也就是说,while(i--)的时候,是先判断i是否满足条件,然后再执行增减。
而while(--i)的时候,是先让i减一再去判断是否满足条件。
所以第一种情况中,i为0的时候被判断不满足条件,不再执行setTimeout,但是后边还是要再-1的,所以最后i变成了-1。
而第二种情况,当i等于1的时候,先让1-1,然后在判断0不满足条件,不再执行i为1时的条件语句,所以循环只有4次,且i最终值也为0。
setTimeout定时器导致的 异步任务
js是单线程的,而浏览器是多线程的。setTimeout属于定时器触发线程中的一种。
因为不能保证任务能够立马执行,所以他被扔到异步队列中,等待回调函数召唤,到时间后再执行。
等时机成熟,回调函数会被安排到主队列中排序入栈被执行。注意这里不要被定时器的时间迷惑了。
理论上执行的时间并不一定就是代码执行时定时器设定的延迟时间之后的时间。因为如果定时器到时,
主任务队列上还轮不着他说话的时候,他也不能插嘴。
同步和任务队列
因为遇到循环里的异步定时器事件,定时器内部的任务被扔到任务队列,等待同步任务执行完毕后执行。
所以循环完毕后,外边的console.log(666)按照同步的顺序先被执行并打印出来。而不是循环内部的console先起作用