felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

JavaScript 之 setTimeout 深入理解 #88

Open felix-cao opened 5 years ago

felix-cao commented 5 years ago

定时器一直是 javascript 动画的核心技术。本文主要讲解 setTimeout。在阅读本文之前,建议先做一道关于 setTimeout 的面试题: 《一道有趣的面试题(setTimeout in for loop)》

一、setTimeout 常规用法

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

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

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

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

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

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

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

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

  [注意]HTML5标准规定,setTimeout的最短时间间隔是4毫秒;setInterval的最短间隔时间是10毫秒,也就是说,小于10毫秒的时间间隔会被调整到10毫秒   大多数电脑显示器的刷新频率是60HZ,大概相当于每秒钟重绘60次。因此,最平滑的动画效的最佳循环间隔是1000ms/60,约等于16.6ms   为了节电,对于那些不处于当前窗口的页面,浏览器会将时间间隔扩大到1000毫秒。另外,如果笔记本电脑处于电池供电状态,Chrome和IE10+浏览器,会将时间间隔切换到系统定时器,大约是16.6毫秒

二、超过两个参数

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

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

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

可以使用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);

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

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

三、返回值为整数

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

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

四、This 指向

由于定时器中的this存在隐式丢失的情况,且极易出错,因此在这里再次进行说明, 详情请移步JavaScript 之 this 的隐式绑定 #90

五、弊端

Reference