JavaScript 定时器
setInterval();
setTimeout();
clearInterval();
clearTimeout();
全局对象window上的方法,内部函数this指向window
注意 :setInterval(“func()”,1000);
定时器分两种,
setInterval() 从名字上叫定时器不太严谨,应该叫定时循环器
setTemeout() 才是真正的定时器,隔了一段时间之后,再执行一个事。换句话说它启的是一个推迟的作用而不是循环执行
一、定时循环器
setInterval() 每隔1000毫秒就执行一次函数,永远没有休止,我们管它叫"定时器"每隔多次多长时间执行一次
setInterval(function(){ // 这个function不用写名字 console.log('a'); },1000); // 1000毫秒的意思
可以把时间调小,调成10速度就非常快,也可以调大2000毫秒,两秒执行一次
setInterval(function(){ console.log('a'); },10);
间隔时间设置到变量time上
var time = 1000; // 间隔时间time setInterval(function(){ console.log('a'); },time); // time这里就是1000 time = 2000; // time在这改成2000,定时器里能变成2000吗?
不可能变,定时器里time会取一次值,每隔time时间执行函数会多次执行函数,但是识别time只识别一次,当初写多少就是多少,不要试图通过改变time来影响setInterval()执行的快慢,当初写1000就是1000后面改不了
可以用setInterval()执行变量加加
var i = 0; setInterval(function(){ i ++; console.log(i); },1000);
可以利用setInterval()做很多东西,
定时间每隔一段时间执行一次函数,这个函数里面的变量就可以变,
通过变化再通过重复执行可以出现很多东西,然后通过这种反复的执行有时间隔的去执行,我们还是可以实现很多状态的连续改变。
测试一下,"定时器"到底准不准?
var firstTime = new Date().getTime(); setInterval(function(){ var lastTime = new Date().getTime(); console.log(lastTime - firstTime); firstTime = lastTime; // 每次都是新生的时刻,减去上一时刻 }, 1000);
应该都是1000才对,程序有时候准有时候不准
程序执行所损耗的毫秒几乎可以不记,程序是以微秒的速度来执行的,首先一定要记住一个结论:setIntervals是非常不准。
然后简单的解释一下,
js引擎后面有一个执行队列,它会把任务按照时间片段去分解,把很多任务的片段排列好,然后往队列里面放,队列依次往执行马达里面去输送,然后马达引擎是单线程同一时间只能执行一个片段,这样依次往里送它才能执行任务。
setIntervals每隔1000毫秒放到队列后面,具体什么时候执行没法保证。当然也不只是这个方面,如果只是这个方面不准永远是慢,为什么还有快的情况!
简单透露一下setInterval的排列机制是基于红黑数的。
PS:
原来业内标志js最底层的书叫《高性能javascript》,现在有一本书刷新记录叫《你不知道的javascript》是最冷门的一些知识,看完后js知识就透了。
clearInterval() 关闭定时器
在clearInterval之前先说一下,
setInterval是window上的方法,由于是window上的方法,我们在全局上不这么写"indow.setInterval也会上GO里面去找,所以不写window也没问题,这是window的一个特点。
setInterval每一个都会返回一个"数字"值,作为它的唯一标识
var timer = setInterval(function(){},1000) console.log(timer); // 1 var timer2 = setInterval(function(){},1000) console.log(timer2); // 2 var timer3 = setInterval(function(){},1000) console.log(timer3); // 3
按照这个唯一标识,可以把定时器清除掉
var i = 0; var timer = setInterval(function(){ console.log(i++); if(i > 10){ clearInterval(timer); // 清除定时器 } }, 10);
数到10定时器就清除了,这是clearInterval清除定时器的方法
当然了,不接收返回值也知道返回值是数字1,直接在clearInterval(1)也行。但这样写不科学,别人不知道为什么写这个1
var i = 0; setInterval(function(){ console.log(i++); if(i > 10){ clearInterval(1); } },1000);
二、定时器
setTemeout() 1000毫秒之后在执行,并且执行一次
setTimeout(function(){ console.log('啦啦'); }, 1000);
setTimeout有什么真实的应用呢?
比如一段电影有一个30秒的试看时间,到30秒之后就看不了,会延迟30秒停掉这个电影把权限关掉。
clearTimeout()
setTimeout它用不用取消?
一部电影同样给五分钟的免费观影时间,五分钟之后就要交钱观看,在这五分钟以内你登录会员了,那五分钟之后就不用停了,那提前预设的任务就应该被取消。
现实在公司里开发的时候,一个移动端的页面从刚开始运行,到整个页面展示结束需要加载3秒左右,最开始设计在三秒钟内不展示广告,在第五秒时才展示广告,所以在第五秒的时候setTimeout把广告展示出来。
但是有一个情况,有两个广告一个弹屏的广告、一个固定位置的广告,五秒钟之内如果点击了固定位置的广告,弹屏的广告就不在展现了,因为两个广告是一回事。
clearTimeout()清除也需要返回值
var timer = setTimeout(function(){ console.log('A'); }, 1000); clearTimeout(timer);
"A"永远出不来了,还没执行就clearTimeout()清除了
setTimeout返回的唯一标识和setInterval返回的唯一标识,不会重叠的返回的是依次的
var timer1 = setInterval(function(){}, 1000); var timer2 = setTimeout(function(){}, 1000); console.log(timer1); // 返回 1 console.log(timer2); // 返回 2
三、全局对象window上的方法,内部函数this指向window
setTimeout和setInterval全是window上的方法,所以内部函数里的this指向的是window
setInterval(function(){ console.log(this); // Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …} } , 1000);
注意setInterval(“func()”,1000);
最后一个注意点,无论是setInterval()还是setTimeout()它们都可以以另一种形式来展现,
第一种形式里面写的是function
setInterval(function () {}, 1000);
另一种形式展现是这样,里面可以写一些字符串,这个字符就会当做js代码来执行
setInterval("console.log('巴拉巴拉')", 1000); // 每个1000毫秒执行一下字符串里面的代码
这是一种特殊的形式,正常情况下不会写种情况,但这种情况确实存在
练习题,
写一个计时器,到三分钟停止
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>练习题 - 计时器</title> <style> input{ border:1px solid rgba(0,0,0,0.2); text-align: right; } </style> </head> <body> minutes:<input type="text" value="0"> seconds:<input type="text" value="0"> <script> var minutesNode = document.getElementsByTagName('input')[0]; var secondsNode = document.getElementsByTagName('input')[1]; var minutes = 0, seconds = 0; var timer = setInterval(function(){ seconds ++; if(seconds == 60){ seconds = 0; minutes ++; } secondsNode.value = seconds; minutesNode.value = minutes; if(minutes == 3){ clearInterval(timer); } }, 100); </script> </body> </html>