博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
setTimeout与setInterval
阅读量:4670 次
发布时间:2019-06-09

本文共 3036 字,大约阅读时间需要 10 分钟。

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

1、setTimeout与setInterval的区别?

 

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

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

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

 

2、看代码,写结果

 

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.

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

 

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

 

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); }

 

4、setTimeout的作用是将代码推迟到指定时间执行,如果指定时间为0,即setTimeout(f,0),那么会立刻执行吗?

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

 

5、看代码,写结果

 

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

 

转载于:https://www.cnblogs.com/zsj-Blog/p/10449006.html

你可能感兴趣的文章
c之枚举默认值
查看>>
设计模式之 --- 工厂模式(下)
查看>>
Linux常用命令大全
查看>>
巴洛克式和哥特式的区别
查看>>
[转载]:C# 中结构与类的区别
查看>>
maven-javadoc-plugin
查看>>
Ubuntu 14.04环境变量修改
查看>>
多线程Lock版生产者和消费者模式
查看>>
zoj3802:easy 2048 again(状压dp)
查看>>
Jenkins 自动化集成之路 Linux 安装 maven
查看>>
vue 自学笔记(七) 组件细节问题
查看>>
CSUOJ 1856 Sokoban 模拟
查看>>
List实体去重
查看>>
python函数回顾:abs()
查看>>
初识大数据(四. 大数据与人工智能的关系)
查看>>
netty 入门(一)
查看>>
Intellij Idea 15 下新建 Hibernate 项目以及如何添加配置
查看>>
《火星!火星!》
查看>>
大道至简读书笔记一
查看>>
php apache 配置后不能正常显示html文件的解决方法
查看>>