setTimeout的那些事

 

一、我们可以设置一个定时器用以指定某个程序在指定时间后才执行

1 setTimeout(function(){
2     console.log("do something");
3 },1000)

用setTimeout,指定1秒后执行

二、当然也可以在想要清除定时器的时候,想办法清除它

只需要给setTimeout起一个别名,clearTimeout这个别名即可

1 // 给定时器起个别名st1
2 var st1 = setTimeout(function(){
3     console.log("do something");
4 },1000)
5 
6 
7 // 清除定时器st1
8 clearTimeout(st1)

别名st1的值为该setTimeout的返回值,该返回值是timeoutID ,是一个正整数,从数字1开始命名,多个定时器其它返回值是从1开始依次编号,即1 2 3 4,表示定时器的编号,这个值可以传递给clearTimeout()来取消该定时器

三、如果你想在指定这个定时器时传递一些参数也是可以的

值得一提的是setTimeout可以传多个参数

setTimeout(function(){}, 时间,参数1,参数2,参数3 ...)

 1 var p1 = '参数1', p2 = '参数2', p3 = '参数3';
 2 
 3 var st1 = setTimeout(function(p1, p2, p3){
 4     console.log("do something 传递的参数:", p1, p2, p3);
 5 },1000, p1, p2, p3)
 6 
 7 // 或者
 8 var st1 = setTimeout(function(a, b, c){
 9     console.log("do something 传递的参数:", a, b, c);
10 },1000,  '参数1',  '参数2',  '参数3')

四、定义多个定时器,且将其赋值给

 1     var st1 = setTimeout(function(i){
 2         console.log(i);
 3     },1000,11)
 4 
 5     var st2 = setTimeout(function(i){
 6         console.log(i);
 7         clearTimeout(st3);
 8     },2000,22)
 9 
10     var st3 = setTimeout(function(i){
11         console.log(i);
12     },3000,33)

执行结果是:

11

22

因为在第7行,清除了定时器st3,因此st3不存在了

五、将setTimeout放在循环中会怎么样

 1 function fn(){
 2     for(var i=0; i<3; i++){
 3         var st1 = setTimeout(function(i){
 4             console.log('x', i);
 5             clearTimeout(st1);
 6         },1,i)
 7         console.log('y', i);
 8     }
 9 }
10 fn();

执行结果是:

y 0

y 1

y 2

x 0

x 1

分析

 

这里用到了Event Loop即事件循环知识,

一段代码,首先要区分是“同步任务”还是“异步任务”,“同步任务”总是早于“异步任务”先顺序执行,

for循环内,只有两大块代码,

分别是:

属于“同步任务”的var定义(但var定义等号右边setTimeout是个“异步任务”)

属于“同步任务”的 console.log('y', i);

具体执行是这样的:

i=0时,遇到var定义,执行var 赋值操作,将st1值赋值为定义setTimeout时的返回值 即 1,但考虑到setTimeout是“异步任务”且细说属于“宏任务”,遂将其添加到“任务队列”的“宏任务”子队列中

这时我们看变量st1的值是第一个setTimeout时定义返回值即这个定时器编号数字1

遇到console.log('y', i); 输出 y 0

i=1时,遇到var定义,执行var 赋值操作,将st1值赋值为定义setTimeout时的返回值 即 2,但考虑到setTimeout是“异步任务”且细说属于“宏任务”,遂将其添加到“任务队列”的“宏任务”子队列中

这时我们看变量st1的值是第二个setTimeout时定义返回值即这个定时器编号数字2

遇到console.log('y', i); 输出 y 1

i=2时,遇到var定义,执行var 赋值操作,将st1值赋值为定义setTimeout时的返回值 即 3,但考虑到setTimeout是“异步任务”且细说属于“宏任务”,遂将其添加到“任务队列”的“宏任务”子队列中

这时我们看变量st1的值是第三个setTimeout时定义返回值即这个定时器编号数字3

遇到console.log('y', i); 输出 y 2

“执行栈”中,“同步任务”代码执行完了,这时就去从“任务队列”中去按“先入先执行”的原则顺序,依次载入“执行栈”,挨个执行,值得一提的是从“任务队列”中调用任务总是先看是否有“微任务”,如果有,则,从“微任务”中,依次载入“执行栈”执行,“微任务”为空,则从“宏任务”调入执行

这里,

1.首先将“编号1的setTimeout”载入“执行栈”执行,输出 x 0 ,其中 clearTimeout(st1),由于此时 st1为“第三个setTimeout时定义返回值即这个定时器编号数字3”,所以,将执行清除“编号3的定时器”动作

2.将“编号2的setTimeout”载入执行栈执行,输出 x 1,再次 clearTimeout(st1) 清除“编号3的定时器”动作

3.由于“宏任务”中“编号3的setTimeout”被清除,因此,“宏任务”被全部执行完毕,程序也到此为止 

原文地址:https://www.cnblogs.com/rapale/p/14979043.html