BOM系列第一篇之定时器setTimeout和setInterval_javascript技巧

setTimeout()

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

  以下代码中,控制台先输出0,大概过1000ms即1s后,输出定时器setTimeout()方法的返回值1

var Timer = setTimeout(function(){
console.log(Timer);
},1000);
console.log(0);

  也可以写成字符串参数的形式,由于这种形式会造成javascript引擎两次解析,降低性能,故不建议使用

var Timer = setTimeout('console.log(Timer);',1000);
console.log(0);

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

  以下代码中,控制台出现0和1,但是0却在前面,后面会解释这个疑问

var Timer = setTimeout(function(){
console.log(Timer);
});
console.log(0);

  实际上,除了前两个参数,setTimeout()方法还允许添加更多的参数,它们将被传入定时器中的函数中

  以下代码中,控制台大概过1000ms即1s后,输出2,而IE9-浏览器只允许setTimeout有两个参数,不支持更多的参数,会在控制台输出NaN

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

  可以使用IIFE传参来兼容IE9-浏览器的函数传参

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

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

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

this指向

  在this机制系列已经详细介绍过this指向的4种绑定规则,由于定时器中的this存在隐式丢失的情况,且极易出错,因此在这里再次进行说明

var a = 0;
function foo(){
console.log(this.a);
};
var obj = {
a : 2,
foo:foo
}
setTimeout(obj.foo,100);//0
//等价于
var a = 0;
setTimeout(function foo(){
console.log(this.a);
},100);//0

  若想获得obj对象中的a属性值,可以将obj.foo函数放置在定时器中的匿名函数中进行隐式绑定

var a = 0;
function foo(){
console.log(this.a);
};
var obj = {
a : 2,
foo:foo
}
setTimeout(function(){
obj.foo();
},100);//2

  或者也可以使用bind方法将foo()方法的this绑定到obj上

var a = 0;
function foo(){
console.log(this.a);
};
var obj = {
a : 2,
foo:foo
}
setTimeout(obj.foo.bind(obj),100);//2

clearTimeout()

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

//过100ms后,控制台输出setTimeout()方法的返回值1
var Timer = setTimeout(function(){
console.log(Timer);
},100);

  于是可以利用这个值来取消对应的定时器

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指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行

<button id="btn">0</button>
<script>
var timer = setInterval(function(){
btn.innerHTML = Number(btn.innerHTML) + 1;
},1000);
btn.onclick = function(){
clearInterval(timer);
btn.innerHTML = 0;
}
</script>

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

  大多数电脑显示器的刷新频率是60HZ,大概相当于每秒钟重绘60次。因此,最平滑的动画效的最佳循环间隔是1000ms/60,约等于16.6ms

  为了节电,对于那些不处于当前窗口的页面,浏览器会将时间间隔扩大到1000毫秒。另外,如果笔记本电脑处于电池供电状态,Chrome和IE 9以上的版本,会将时间间隔切换到系统定时器,大约是16.6毫秒

运行机制

  下面来解释前面部分遗留的疑问,为什么下面代码的控制台结果中,0出现在1的前面呢?

setTimeout(function(){
console.log(1);
});
console.log(0);

  实际上,把setTimeout的第二个参数设置为0s,并不是立即执行函数的意思,只是把函数放入代码队列

  在下面这个例子中,给一个按钮btn设置了一个事件处理程序。事件处理程序设置了一个250ms后调用的定时器。点击该按钮后,首先将onclick事件处理程序加入队列。该程序执行后才设置定时器,再有250ms后,指定的代码才被添加到队列中等待执行

btn.onclick = function(){
setTimeout(function(){
console.log(1);
},250);
}

  如果上面代码中的onclick事件处理程序执行了300ms,那么定时器的代码至少要在定时器设置之后的300ms后才会被执行。队列中所有的代码都要等到JavaScript进程空闲之后才能执行,而不管它们是如何添加到队列中的

  如图所示,尽管在255ms处添加了定时器代码,但这时候还不能执行,因为onclick事件处理程序仍在运行。定时器代码最早能执行的时机是在300ms处,即onclick事件处理程序结束之后

setInterval的问题

  使用setInterval()的问题在于,定时器代码可能在代码再次被添加到队列之前还没有完成执行,结果导致定时器代码连续运行好几次,而之间没有任何停顿。而javascript引擎对这个问题的解决是:当使用setInterval()时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。这确保了定时器代码加入到队列中的最小时间间隔为指定间隔

  但是,这样会导致两个问题:1、某些间隔被跳过;2、多个定时器的代码执行之间的间隔可能比预期的小

  假设,某个onclick事件处理程序使用serInterval()设置了200ms间隔的定时器。如果事件处理程序花了300ms多一点时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过某间隔的情况

  例子中的第一个定时器是在205ms处添加到队列中的,但是直到过了300ms处才能执行。当执行这个定时器代码时,在405ms处又给队列添加了另一个副本。在下一个间隔,即605ms处,第一个定时器代码仍在运行,同时在队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中

迭代setTimeout

  为了避免setInterval()定时器的问题,可以使用链式setTimeout()调用

setTimeout(function fn(){
setTimeout(fn,interval);
},interval);

  这个模式链式调用了setTimeout(),每次函数执行的时候都会创建一个新的定时器。第二个setTimeout()调用当前执行的函数,并为其设置另外一个定时器。这样做的好处是,在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔。而且,它可以保证在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行

  使用setInterval()

<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div>
<script>
myDiv.onclick = function(){
var timer = setInterval(function(){
if(parseInt(myDiv.style.left) > 200){
clearInterval(timer);
return false;
}
myDiv.style.left = parseInt(myDiv.style.left) + 5 + 'px';
},16);
}
</script>

  使用链式setTimeout()

<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div>
<script>
myDiv.onclick = function(){
setTimeout(function fn(){
if(parseInt(myDiv.style.left) <= 200){
setTimeout(fn,16);
}else{
return false;
}
myDiv.style.left = parseInt(myDiv.style.left) + 5 + 'px';
},16);
}
</script>

应用

  使用定时器来调整事件发生顺序

  【1】网页开发中,某个事件先发生在子元素,然后冒泡到父元素,即子元素的事件回调函数,会早于父元素的事件回调函数触发。如果,我们先让父元素的事件回调函数先发生,就要用到setTimeout(f, 0)

  正常情况下,点击div元素,先弹出0,再弹出1

<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;"></div>
<script>
myDiv.onclick = function(){
alert(0);
}
document.onclick = function(){
alert(1);
}
</script>

  如果进行想让document的onclick事件先发生,即点击div元素,先弹出1,再弹出0。则进行如下设置

<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;"></div>
<script>
myDiv.onclick = function(){
setTimeout(function(){
alert(0);
})
}
document.onclick = function(){
alert(1);
}
</script>

  【2】用户自定义的回调函数,通常在浏览器的默认动作之前触发。比如,用户在输入框输入文本,keypress事件会在浏览器接收文本之前触发。因此,下面的回调函数是达不到目的

<input type="text" id="myInput">
<script>
myInput.onkeypress = function(event) {
this.value = this.value.toUpperCase();
}
</script>

  上面代码想在用户输入文本后,立即将字符转为大写。但是实际上,它只能将上一个字符转为大写,因为浏览器此时还没接收到文本,所以this.value取不到最新输入的那个字符

  只有用setTimeout改写,上面的代码才能发挥作用

<input type="text" id="myInput">
<script>
myInput.onkeypress = function(event) {
setTimeout(function(){
myInput.value = myInput.value.toUpperCase();
});
}
</script> 

代码到此结束。下篇给大家介绍

BOM系列第二篇之定时器requestAnimationFrame

BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)

以上所述是小编给大家介绍的BOM系列第一篇之定时器setTimeout和setInterval ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索bom
定时器
js定时器setinterval、定时器setinterval、jq定时器setinterval、js定时器settimeout、清除settimeout定时器,以便于您获取更多的相关知识。

时间: 2024-12-03 06:55:00

BOM系列第一篇之定时器setTimeout和setInterval_javascript技巧的相关文章

BOM系列第二篇之定时器requestAnimationFrame_javascript技巧

引入 计时器一直是javascript动画的核心技术.而编写动画循环的关键是要知道延迟时间多长合适.一方面,循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅:另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化 大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次.大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升.因此,最平滑动画的最佳循环间隔是lOOOms/60,约等于16.6ms 而setTimeout和

深入理解ajax系列第一篇之XHR对象_AJAX相关

前面的话 ajax是asynchronous javascript and XML的简写,中文翻译是异步的javascript和XML,这一技术能够向服务器请求额外的数据而无须卸载页面,会带来更好的用户体验.虽然名字中包含XML,但ajax通信与数据格式无关.下面将详细介绍ajax的内容  创建 ajax技术的核心是XMLHttpRequest对象(简称XHR),这是由微软首先引入的一个特性,其他浏览器提供商后来都提供了相同的实现.XHR为向服务器发送请求和解析服务器响应提供了流畅的接口,能够以

理解javascript定时器中的setTimeout与setInterval_javascript技巧

一.解释说明 1.概述 setTimeout:在指定的延迟时间之后调用一个函数或者执行一个代码片段 setInterval:周期性地调用一个函数(function)或者执行一段代码. 2.语法 setTimeout: var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]); var timeoutID = window.setTimeout(code, delay); timeoutID 是该延时操作的数字ID,

ASP基础入门第一篇(ASP技术简介)_应用技巧

本文将以如何建立基于IIS 的ASP 动态网站为中心向大家一步一步地揭示动态商业网站设计的真正奥秘.为了使各位能够全面.细致地掌握 ASP 的开发技巧,本文今后将采取连载的形式,手把手地教你如何建立属于自己 ASP 动态网站.由于本文是作者根据自己的学习和实践经验并结合了一些外文资料而写成的,因此不免会有一些偏颇,希望各位见谅. Microsoft Active Server Pages 即我们所称的ASP ,其实是一套微软开发的服务器端脚本环境, ASP 内含于 IIS 3.0 和 4.0 之

.NET CIL系列第一篇:CIL介绍和入门

CIL编程的本质 CIL是英文Common Intermediate Language的简写.CIL本质上其实就是.NET平台的母语.当开发人员选择一种托管的编程语言(C#.VB.COBOL.NET等)构建.NET程序集时,同这个语言相关的编译器就会把源代码编译成CIL.正如其他任何一种编程语言一样,CIL提供了非常多的结构和实现标记.如果考虑到CIL其实也是一种.NET的编程语言,那么通过直接使用.NET Framework 3.5 SDK提供的CIL和CIL编译器(ilasm.exe)来开发

机器学习能为你的业务做什么?有些事情你肯定猜不到!(机器学习入门系列第一篇)

每一个产品经理.企业家或商业领袖都应该让自己的项目或企业在机器学习方面加速发展.如果你还没有建立起下一个代的聊天室或自动驾驶汽车,那么你需要加快引入机器学习的进度,以保持较强的竞争力.有一个好消息,对于机器学习,你无需自己发明,只需利用现成的就可以了.一些技术公司已经提供了开源的工具和平台(Amazon AI,TensorFlow, 和许多其他工具),使得任何公司在今天都可以使用机器学习. 当我初次踏入机器学习门槛的时候,我对此几乎一无所知,但是在很短的时间里,我就能以机器学习为技术核心指挥产品

浅谈setTimeout 与 setInterval_javascript技巧

最新写代码中时,看到项目中有人用到了 setTimeout(fun,0),于是想总结一下.个人理解,如果有错误的地方还请指出.THX 要想理解JavaScript的定时器是如何工作的,先要明白 JavaScript 引擎是单线程的.这个可以理解为 javascript 引擎是一个服务员,它有一个服务的队列,所有的界面元素事件,定时触发器回调,异步请求回调都要在这个任务队列里排队,等待处理.所有任务都是一个最小单位,不会中断处理.这样就可以理解 setTimeout(fun,0) 了,它并不是代表

BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)_javascript技巧

时钟 最简单的时钟制作办法是通过正则表达式的exec()方法,将时间对象的字符串中的时间部分截取出来,使用定时器刷新即可 <div id="myDiv"></div> <script> myDiv.innerHTML = /\d\d:\d\d:\d\d/.exec(new Date().toString())[0]; setInterval(function(){ myDiv.innerHTML = /\d\d:\d\d:\d\d/.exec(new

CoreOS Fest 系列之第一篇:容器江湖

本文讲的是CoreOS Fest 系列之第一篇:容器江湖,[编者的话] 这是总结 CoreOS Fest 大会的三篇文章之一,主要介绍了 CoreOS 公司与 Docker 公司之争,新成立的 appc 规范委员会, Tectonic 平台, Kubernetes 项目. 最近在旧金山, Linux 容器已经显得非常有「钱」景,看起来每个人都想从这个有几十亿美金规模的新市场中分得一杯羹.多家创业公司和云主机公司已经或者即将召开有关容器的大会,包括 4 月 17 日召开的 Container Ca