Go to comments

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() 执行变量 i 加加

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 才对,程序有时候准有时候不准

图片.png


程序执行所损耗的毫秒几乎可以不记,程序是以微秒的速度来执行的,首先一定要记住一个结论:setIntervals 是非常不准


然后简单的解释一下,

js 引擎后面有一个执行队列,它会把任务按照时间片段去分解,把很多任务的片段排列好,然后往队列里面放,队列依次往执行马达里面去输送,然后马达引擎是单线程同一时间只能执行一个片段,这样依次往里送它才能执行任务。


setInterval 每隔 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 清除定时器的方法

图片.png


当然了,不接收返回值也知道返回值是数字 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 秒停掉这个电影把权限关掉。


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毫秒执行一下字符串里面的代码

这是一种特殊的形式,正常情况下不会写种情况,但这种情况确实存在

图片.png


练习题,

写一个计时器,到三分钟停止

<!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>



Leave a comment 0 Comments.

Leave a Reply

换一张