JavaScript提供定时器(timer)的功能,可以延期执行或重复执行函数或代码段。

window对象提供了三个方法来实现定时器的效果,分别是setTimeout()、setInternal()和requestAnimationFrame()。

定时器是JavaScript动画的核心技术。

setTimeout()

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

var timer = setTimeout(function() {
console.log(timer); // 2.1000ms后,再输出1(1是定时器的编号)
}, 1000);
console.log(0); // 1.先输出0

也可以写成字符串参数的形式,但是这种形式会造成JavaScript引擎的二次解析,降低性能,因此并不推荐使用。

var timer = setTimeout("console.log(timer);", 1000);
console.log(0);

如果省略setTimeout的第二个参数,则该参数默认为0。

var Timer = setTimeout(function() {
console.log(Timer); // 2.过了0ms后,再输出1
});
console.log(0); // 1.先输出0

实际上,除了上面提到的两个参数之外,setTimeout还允许添加更多的参数,它们将被传入到定时器的函数之中。

setTimeout(function(a,b) {
console.log(a + b); // 等待1000ms后,输出2
}, 1000, 1, 1);

要注意的是,IE9及以下的浏览器只支持setTimeout有两个参数,最后的输出结果会是NaN(名副其实的Fuck-IE),这时候可以使用IIFE传参来进行兼容。

setTimeout((function(a, b) {
return function() {
console.log(a + b);
}
})(1, 1), 1000);

或者也可以将函数写在定时器的外面,然后函数在定时器的匿名函数中带参数调用。

function calc(a, b) {
console.log(a + b);
}
setTimeout(function() {
calc(1, 1);
}, 1000);

要注意的是,IE8浏览器不允许向定时器中传递事件对象event,如果要使用事件对象中的某些属性,可以将其保存在变量中传递进去。

div.onclick = function(e) {
e = e || event;
var type = e.type;
setTimeout(function() {
console.log(type); // click
console.log(e.type); // 报错
})
}

cleartimeout()

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

var Timer = setTimeout(function() {
console.log(Timer);
}, 100);
clearTimeout(Timer);

或者直接使用返回值作为参数。

var Timer = setTimeout(function() {
console.log(Timer);
}, 100);
clearTimeout(1);

一般来说,setTimeout返回的整数值是连续的,也就是说,第二个setTimeout方法返回的整数值比第一个的整数值大1。

// 控制台输出1、2、3
var Timer1 = setTimeout(function() {
console.log(Timer1);
}, 100);
var Timer2 = setTimeout(function() {
console.log(Timer2);
}, 100);
var Timer3 = setTimeout(function() {
console.log(Timer3);
}, 100);

setInterval()

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

var count = 0;
var timer = setInterval(function() {
console.log(count++);
}, 1000);

要注意的是,HTML5的标准规定,setTimeout的最短时间间隔是4毫秒;setInterval的最短间隔时间是10毫秒,也就是说,小于10毫秒的时间间隔会被调整到10毫秒。

requestAnimationFrame

计时器一直是javascript动画的核心技术。而编写动画循环的关键是要知道延迟时间多长合适。一方面,循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化。

大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。因此,最平滑动画的最佳循环间隔是1000ms/60,约等于16.6ms。

而setTimeout和setInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行。

requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

也就是说,requestAnimationFrame与setTimeout、setInterval不同,不需要设置时间间隔。

requestAnimationFrame的特点

1.requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。

2.在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量。

3.requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。

requestAnimationFrame的使用

requestAnimationFrame的用法与settimeout很相似,只是不需要设置时间间隔而已。requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行。

requestID = requestAnimationFrame(callback); 
// 控制台输出1和0
var timer = requestAnimationFrame(function() {
console.log(0);
});
console.log(timer); //
// 控制台什么都不输出
var timer = requestAnimationFrame(function() {
console.log(0);
});
cancelAnimationFrame(timer);

也可以直接使用返回值进行取消。

var timer = requestAnimationFrame(function() {
console.log(0);
});
cancelAnimationFrame(1);

requestAnimationFrame的兼容

IE9浏览器及以下不支持这个方法,可以使用setTimeout来兼容。

// 简单兼容
if (!window.requestAnimationFrame) {
requestAnimationFrame = function(fn) {
setTimeout(fn, 17);
};
}
// 严格兼容
if(!window.requestAnimationFrame) {
var lastTime = 0;
window.requestAnimationFrame = function(callback) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0,16.7 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
}
} if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}

"最怕你一生碌碌无为,还要安慰自己平凡可贵。"

javascript中的定时器入门的更多相关文章

  1. javascript中的定时器

    本文地址:[http://www.xiabingbao.com/javascript/2015/04/20/javascript-timer/] 在以前的文章[javascript中的定时器]中,简单 ...

  2. [ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!

    作为入门者来说.了解JavaScript中timer的工作方式是非常重要的.通常它们的表现行为并非那么地直观,而这是由于它们都处在一个单一线程中.让我们先来看一看三个用来创建以及操作timer的函数. ...

  3. 浅谈JavaScript中的定时器

    引言 使用setTimeout()和setInterval()创建的定时器可以实现很多有意思的功能.很多人认为定时器是一个单独的线程(之前我也是),但是JavaScript是运行在单线程环境中的,而定 ...

  4. javascript中的计时器

    javascript中的定时器有两种:一种是一次性定时器,一种是可以持续使用的定时器: 1:一次性定时器setTimeout(a,b):兼容ie的任何版本 该方法接受两个参数,第一个是要执行的代码,第 ...

  5. Unity中的定时器与延时器

    JavaScript中的定时器与延时器,分别是 setInterval.setTimeout,对应的清理函数是:clearInterval.clearTimeout. 而在Unity中,则分别是:In ...

  6. Javascript中定时器的使用方法

    Javascript中定时器的使用方法 1.间隔定时器(每隔一段时间执行一次代码) 格式:setInterval(函数,时间) //时间单位是毫秒,每隔设置的时间执行函数里的内容一遍(一直执行) // ...

  7. javaScript中Number数字类型方法入门

    前言 Number和Math都属于JavaScript中的内置对象,Number数字类型作为基础数据类型,我们在开发过程中会经常用到,包括数字精度的格式化,还有字符串转换成数字等操作. Number数 ...

  8. javaScript中Math内置对象基本方法入门

    概念 Math 是javaScript的内置对象,包含了部分数学常数属性和数学函数方法. Math 不是一个函数对象,用户Number类型进行使用,不支持BigInt. Math 的所有属性与方法都是 ...

  9. 快速入门上手JavaScript中的Promise

    当我还是一个小白的时候,我翻了很多关于Promise介绍的文档,我一直没能理解所谓解决异步操作的痛点是什么意思 直到我翻了谷歌第一页的所有中文文档我才有所顿悟,其实从他的英文字面意思理解最为简单粗暴 ...

随机推荐

  1. CSS中@support的用法

    这段时间一直在调试浏览器的兼容性问题,了解到了@support的这个属性,记录下: CSS中的@support主要是用于检测浏览器是否支持CSS的某个属性,其实就是条件判断,如果支持某个属性,你可以写 ...

  2. elementui入门

    1.前端服务器搭建 (1)创建一个static web project (2) 安装 npm install -g vue-cli (3) vue init webpack 项目名 (4)cd 项目名 ...

  3. CCF-CSP题解 201403-4 无线网络

    新建不超过\(k\)个无线路由器,求使路由器1.2连通最少的中间路由器. 首先常规建图,将相距不超过\(r\)的路由器(包括新建的)相连. 想到了分层\(dijkstra\).类似的,作\(bfs\) ...

  4. AQS系列(五)- CountDownLatch的使用及原理

    前言 前面四节学完了AQS最难的两种重入锁应用,下面两节进入实战学习,看看JUC包中其他的工具类是如何运用AQS实现特定功能的.今天一起看一下CountDownLatch. CountDownLatc ...

  5. Python连载58-http协议简介

    一.http协议实战 1.URL(Uniform Resource Located) (1)使用FFTP的URL,例如:ftp://rtfm.mit.edu (2)使用HTTP的URL,例如:http ...

  6. Mysql基于Mysql Cluster+MysqlRouter的集群部署方案

    http://note.youdao.com/noteshare?id=a61c4a6ff2b76e5305430eb66eb116e2&sub=4B4B6E8D0E2849F9B0DFB67 ...

  7. Android Healthd电池服务分析

    healthd healthd是安卓4.4之后提出来的,监听来自kernel的电池事件,并向上传递电池数据给framework层的BatteryService.BatteryService计算电池电量 ...

  8. Linux 删除特殊字符文件名或目录

    通过文件的inode号删除文件 先用ls -i 找出要删除文件的inode 号 ls -i |grep xxxxxx|awk '{print $2}'|xargs -i rm -f {} xxxxxx ...

  9. Aery的UE4 C++游戏开发之旅(2)编码规范

    目录 C++基础类型规范 命名规范 头文件规范 字符串规范 字符集规范 参考 C++基础类型规范 由于PC.XBOX.PS4等各平台的C++基础类型大小可能不同(实际上绝大部分都是整型类型的大小不同) ...

  10. mariadb 学习笔记

    安装:yum install mariadb-server mariadb vim /etc/my.cnf.d/server.cnfinnodb_file_per_table = on#设置后当创建数 ...