定时器(setTimeout)的秘密
原文地址:→传送门
写在前面
setTimeout()是大家再熟悉不过的定时器,但平时对定时器的了解甚少,于是想看看setTimeout()的原理机制。
setTimeout()基础
setTimeout()函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。
var timeer = setTimeout(function|code,delay);
注:其中为code时需要以字符串形式传入,一般都是使用传入function的形式。
setTimeout(func,delay,arg1,arg2···)
setTimeout()可传入多个参数,第三个参数起是作为回调函数的参数传入。
function add(a,b){
console.log(a+b);
}
setTimeout(add,4000,20,30); //20和30作为add的参数传入 结果为50
HTML5规定setTimeout()的最短时间间隔是4ms,对于不处在当前窗口的页面,浏览器会将时间间隔扩大到1000ms,若笔记本电脑处于电池供电状态,chrome及IE9以上版本,会将时间间隔切换到系统定时器,约15.6ms。
setTimeout()中回调函数的指向
setTimeout()回调函数调用的是某个对象的方法,则其中this指向的是setTimeout所处的环境而并非指向该对象环境。
可使用ES5中的bind()方法解决this指向,即将对象环境绑定到要执行的回调函数上即可。
var name = 'lily';
function Person(name){
this.name = name;
this.printName = function(){
console.log(this.name);
}
}
var person01 = new Person('jike');
//此处的this.name为window下的name,所以是'lily'
window.setTimeout(person01.printName,1000);
//此处将printName绑定在person01上,所以this.name的值为'jike'
window.setTimeout(person01.printName.bind(person01),2000);
//将printName中的this.name与person01限定在同一个作用域中,所以结果是'jike'
window.setTimeout(function(){person01.printName();},3000);
//借助ES6中的箭头函数也可以解决问题
window.setTimeout(() => {person01.printName},1000);
setTimeout运行机制
setTimeout()和setInterval()的运行机制是,将指定的代码移出本次执行,等到下一轮Event Loop时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop时重新判断。这意味着,setTimeout()指定的代码,必须等到本次执行的所有代码都执行完,才会执行。
例如:
task1();
setTimeout(otherTask,1000);
task2();
其中task1和task2为立即执行任务,otherTask被指定在1s后执行,此时otherTask被添加到任务队列的尾部,要等当前的脚本中Event Loop的任务队列全部执行完成后,才开始执行otherTask,但如果task1和task2很耗时,前面的任务超过1s还未结束,此时otherTask只能等task1和task2运行结束,才会执行otherTask。
setTimeout(func,0)的运用
当延迟时间设为0时,即当前任务队列一结束就立即执行func。(换个角度说就是同步任务的任务队列结束后尽早执行。)
task01();
setTimeout(function(){
console.log('hello!'); //在task01和task02结束后立即打印hello!
},0)
task02();
0ms在实际上是达不到的,根据HTML5标准,setTimeout()推迟执行的时间最少是4ms,如果小于这个值,会被自动增加到4,同时也是为了防止多个setTimeout(func,0)语句连续执行,造成性能问题。
- setTimeout(func,0)可以调整事件的发生顺序。
clearTimeout()
setTimeout()和setInterval()函数,都返回一个表示计数器编号的整数值,将该整数传入clearTimeout()和clearInterval()函数,就可以取消对应的定时器。两种定时器用的同一个编号池。
setTimeout()和setInterval()函数返回的整数值都是连续的,因此可以利用循环来清除所有的定时器。
防抖动(debounce)
该方法用于防止某个函数在短时间内被密集调用,具体来具体来说,debounce方法返回一个新版的该函数,这个新版函数调用后,只有在指定时间内没有新的调用,才会执行,否则就重新计时。
实际中不要设置太多个setTimeout()和setInterval(),它们耗费CPU,理想做法是将要延迟执行的代码都放在同一个函数里,然后支队这个函数使用setTimeout()和setInterval()。
setInterval()
setInterval()使用原理机制与setTimeout()一样,区别就是setInterval()是每隔多少ms执行一次回调函数。也可以传入大于两个参数。
setInterval()指定的是“开始执行”之间的间隔,并不考虑每次任指定的是“开始执行”之间的间隔,并不考虑每次任,比如,setInterval()指定每100ms执行一次,每次执行需要5ms,那么第一次执行后95ms后,第二次执行就会开始。如果某次执行需要105ms,即超过了delay时间,则执行结束后下一次执行就会立即开始。
setInterval()的最短间隔是10ms,小于10ms的时间间隔会被调整到10ms
setInterval()具有累积效应,如果某个操作特别耗时,超过了setInterval()的时间间隔,排在后面的操作就会被累积起来,然后在很短的时间内连续触发,这可能会造成性能问题。
资源参考
定时器(setTimeout)的秘密的更多相关文章
- 关于定时器 setTimeout
1.这里不考虑线程问题.把javascript想象成在时间线上运行,页面载入时,首先执行的是<script>标签中的代码,之后,将执行更多代码,当进程空闲时,下个代码就被触发并执行 如图: ...
- Javascript 笔记与总结(2-13)定时器 setTimeout 和 setInterval
定时器可以让 js 效果每隔几秒钟执行一次或者 n 秒之后执行某一个效果.定时器不属于 javascript,是 window 对象提供的功能. setTimeout 用法: window.setTi ...
- javascript定时器:setTimeout与setInterval
概述: setTimeout:在指定的延迟时间之后调用一个函数或者执行一个代码片段,只执行一次: setInterval:周期性地调用一个函数(function)或者执行一段代码,重复执行: 语法格式 ...
- 定时器setTimeout()和Node.js的Event Loop
一.定时器 setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行.它在"任务队列"的尾部添加一个事件,因此要等到同步任务和 ...
- 关于定时器setTimeout()方法的实践--巧解bug
_使用开发环境:UAP:_ _框架:JQuery.MX:_ 最近的开发的页面中,有一处需要在提交的 datagrid里启用行编辑,就会发生奇怪的bug,编辑过程中如图所示不移开焦点直接点保存,那么已输 ...
- 定时器 setTimeout()超时调用和 setInterval()间歇调用
JavaScript是单线程语言,但它允许通过设置定时器,也就是设置超时值和间歇时间来调度代码在特定的时刻执行.前者是在指定的时间过后执行代码,而后者则是每隔指定的时间就执行一次代码. 超时调用需要使 ...
- 移动端长按响应事件以及阻止默认行为e.preventDefault()导致定时器setTimeout不能响应
手指触摸绑定: $(document).on('touchstart', '.photo', function(e){ currentIndex = parseInt($(this).index('. ...
- 定时器setTimeout实现函数节流
问题描述 文字输入查询的keyup或oninput事件,实现实时查询功能. 在用户输入过程中,用户可能只想需要 '小' 字的查询结果,但是以上两个事件会触发'x'.'i'.'a'.'o'.'小',一共 ...
- JavaScript之关闭轮询定时器(setTimeout/clearTimeout|setInterval/clearInterval)小结
已知: 1.1 开启Timeout程序: scope.setTimeout("functionName()" | functionHandle, timeValue) 返回值:ti ...
- JS 定时器 setTimeout 与 setInterval 的区别和用法
定时器: window.setTimeout(function(){},间隔时间毫秒); -- 定时炸弹,延迟执行,只执行一次 window.setInterval(function(){},间隔的时 ...
随机推荐
- Java虚拟机14:Java对象大小、对象内存布局及锁状态变化
一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...
- MyBatis介绍
MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis 使用简单的 XML或注解用于配 ...
- vue-resource promise兼容性问题
背景 其实这个问题在之前的项目开发中就出现过,但是当初只解决问题了,并没有针对问题作总结:于是乎今天踩到了自己埋的坑,所以决定记录一下.那么到底是什么问题呢?就是"在安卓低版本,如果你在vu ...
- 小试牛刀JavaScript鼠标事件
鼠标事件练习1 当鼠标点击网页某个单元格的时候,其他的单元格颜色不变,只有被点击的单元格颜色发生变化 <style type="text/css"> *{ margin ...
- Scrapy爬虫大战京东商城
Scrapy爬虫大战京东商城 引言 上一篇已经讲过怎样获取链接,怎样获得参数了,详情请看python爬取京东商城普通篇 代码详解 首先应该构造请求,这里使用scrapy.Request,这个方法默认调 ...
- python 文件操作(pickle)
>>> with open('text.txt','wb') as data:pickle.dump(['a','b',2],data) 保存到文件 >>> wit ...
- Kubernetes服务之StatefulSets简介
StatefulSets在v1.5时还是个beta特性,它取代了v1.4的PetSets特性.PetSets的用户可以参考v1.5的升级指导,将正在运行的PeetSets升级到StatefulSets ...
- js中的匿名函数自执行
随笔,java中因为有修饰符的存在,那就有private类的存在,js不一样,没有修饰词一说,因此为了防止全局变量的污染,js中就出现了匿名函数,直接上code,看到的人可以自己体会: (functi ...
- php7 安装yar 生成docker镜像
Docker包含三个概念:(1)远程仓库即远程镜像库所有镜像的聚集地(不可进入操作).(2)本地镜像即从远程仓库拉取过来的镜像(3)运行起来的本地镜像叫做容器(分层的可操作)Docker使用:1.首先 ...
- Oracle数据库中的重要对象
数据库中的重要对象:表.视图.序列.函数.存储过程.索引.同义词1.表:用PL/SQL Developer 软件打开 Scott的DEPT表查看SQL,可以看见DEPT表创建的脚本-- Create ...