setTimeout与setInterval

前言:关于最近面试遇到的setTimeout与setInterval相关面试题,网上搜索相关资料,进行学习总结。javascript

一、setTimeout与setInterval的区别?
java

 

setTimeout()方法用来指定某个函数或字符串在指定的毫秒数以后执行。它返回一个整数,表示定时器的编号,这个值能够传递给clearTimeout()用于取消这个函数的执行。面试

setInterval的用法与setTimeout彻底一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。promise

setTimeout和setInterval函数,都返回一个表示计数器编号的整数值,将该整数传入clearTimeout和clearInterval函数,就能够取消对应的定时器。异步

 

二、看代码,写结果
函数

 

for (var i = 0; i < 5; i++) { 
  setTimeout(function (){
    console.log(i); 
   },1000); 
}

结果:5,5,5,5,5学习

 

 setTimeout是异步执行的,1000毫秒后向任务队列里添加一个任务,只有主线上的所有执行完才会执行任务队列里的任务,因此当主线程for循环执行完以后i的值为5,这个时候再去任务队列中执行任务,i所有为5;每次for循环的时候setTimeout都会执行,可是里面的function不会执行,所以放了5次,1000毫秒后所有执行完任务队列中的函数,因此输出五个5.spa

同时,i是var定义的,不属于for循环体,属于全局global。等for循环结束,i已经等于5了,这个时候执行回调函数,里面console.log(i)的i向上找做用域,只能找到全局下的i,即5.因此输出都是5.线程

 

三、如何解决上述问题,变成0,1,2,3,4code

 

a、当即执行函数

这样console.log(i)中的i就保存在每一次循环生成的当即执行函数中对的做用域里了。

for (var i = 0; i < 5; i++) { 
  (function(i){   //马上执行函数
    setTimeout(function (){
      console.log(i); 
     },1000); 
  })(i); 
}

 

b、let做为代码块做用域,因此每一次 for 循环,console.log(i); 都引用到 for 代码块做用域下的i,由于这样被引用,因此 for 循环结束后,这些做用域在 setTimeout 未执行前都不会被释放。

for (let i = 0; i < 5; i++) {   //let 代替 var
  setTimeout(function (){
    console.log(i); 
   },1000); 
}

 

四、setTimeout的做用是将代码推迟到指定时间执行,若是指定时间为0,即setTimeout(f,0),那么会马上执行吗?

不会。必须等当前脚本的同步任务和队列任务中全部事件执行完,才会执行setTimeout指定任务,将第二参数设置为0,目的是以前全部任务执行完后就当即执行,尽量早得执行指定任务

 

五、看代码,写结果

 

console.log("script start");
setTimeout(function(){
console.log("setTimeout");
},0);
Promise.resolve().then(function(){
console.log("promise1");
}).then(function(){
console.log("promise2");
});
console.log("script end");

结果:

script start
script end
promise1
promise2
setTimeout

 setTimeout和Promise调用都是异步任务,都是经过任务队列进行管理调度。分为宏任务队列和微任务队列,能够看出Promise比setTimeout()先执行。由于Promise定义以后便会当即执行,其后的.then()是异步里面的微任务。而setTimeout()是异步的宏任务。

从script(总体代码)开始第一次循环,全局上下文进入函数调用栈(栈底),若是有可执行代码就进行正常的入栈出栈,若是有上面提到的setTimeout和Promise,就将任务分发到各自队列,直到调用栈清空(只剩全局),而后执行全部的微任务队列(Promise队列),这就是第一次循环。当全部可执行的微任务执行完毕以后,循环再次从宏任务(setTimeout队列)开始执行入栈出栈任务分发等,执行完毕,而后再执行全部的微任务,第二次循环结束。。。这样一直循环下去,直到再也没有可执行的任务。这就是JS的循环机制。

console.log('打印'+1);
setTimeout(function(){
    console.log('打印'+2);
})
new Promise(function(resolve,reject){
        console.log('打印'+3);
      }).then(
  console.log('打印'+4));;
console.log('打印'+10);
new Promise(function(resolve,reject){
      setTimeout(function () {
        console.log('打印'+5);
      });
  }).then(
  console.log('打印'+6));
setTimeout(function(){
    new Promise(function(resolve,reject){
        console.log('打印'+7);
      });
})

打印1
打印3
打印4
打印10
打印6
打印2
打印5
打印7

 

console.log('打印'+1);
setTimeout(function(){
    console.log('打印'+2);
})
new Promise(function(resolve){
        console.log('打印'+3);
        resolve();
      }).then(function(){
        console.log(4);
      }
  );
console.log('打印'+10);
new Promise(function(resolve){
      setTimeout(function () {
        console.log('打印'+5);
      });
      resolve();
  }).then(function(){

  console.log('打印'+6)});
setTimeout(function(){
    new Promise(function(resolve){
        console.log('打印'+7);
      });
})

打印1打印3打印10 4打印6打印2打印5打印7

相关文章
相关标签/搜索