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>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,并不是立即执行函数的意思,只是把函数放入代码队列