JavaScript定时器setTimeout与setInterval深度解析:原理、差异及最小延时限制
本文深入解析JavaScript中setTimeout与setInterval的使用方法及底层执行机制。通过对比一次性与重复性定时器的实现差异,阐明任务队列中的执行顺序。重点讲解嵌套调用时的4ms最小延时限制原理,并提供清除定时器的最佳实践,帮助开发者避免内存泄漏并优化代码性能。
定时器基本概念与setTimeout语法
从直观概念来看,定时器是一种在指定时间到达后触发特定动作的机制。
在程序逻辑中,定时器类似于倒计时或计时器,其核心功能是在预设的时间间隔结束后,自动执行指定的回调函数。
首先介绍setTimeout定时器,其显著特征是仅执行一次,因此也被称为一次性定时器。
setTimeout( func, time, argument1, argument2, .... ); 语法解析: 1、func:固定时间后执行的方法 2、time:设置固定的时间-按毫秒计算 3、argument:传入方法的参数 案例:
setTimeout(function(name,gender){ console.log(name + " is " + gender); }, 1000, "Tom", "boy");简写:
setTimeout((name,gender) => { console.log(name + " is " + gender); }, 1000, "Tom", "boy");案例解析: 开启了一个一次性定时器,1秒后执行我给定的函数。
setInterval与任务队列执行机制
接下来介绍setInterval定时器,其核心特点是能够重复执行给定的回调函数。
console.log("1 ===>");
setTimeout(function(name,gender){
console.log(name + " is " + gender);
}, 1000, "Tom", "boy");
console.log("2 ===>");
执行结果:
> "1 ===>"
> "2 ===>"
> "Tom is boy"接下来就开始圈重点了:
理解了定时器的基本概念和创建方式后,需要明确其调用时机。由于JavaScript代码是逐行同步执行的,当代码执行到定时器语句时,主线程并不会等待定时器执行完毕,而是继续向下执行后续代码。
遇到定时器,会将定时器加入到任务队列中(宏任务),等所有代码执行完了,程序会看一下队列中还有什么没有完成的 ,如果有没完成的,就执行一下。
这样说可能有点抽象,看下案例好了。
console.log("1 ===>");
setTimeout(function(name,gender){
console.log(name + " is " + gender);
}, 1000, "Tom", "boy");
console.log("2 ===>");
执行结果:
> "1 ===>"
> "2 ===>"
> "Tom is boy"注意:任务队列里的执行顺序是按先来后到的
一次性与重复性定时器的底层差异
接下来再深入理解一下,我们先思考一个问题,一次性定时器和重复性定时器区别在哪,不可能就只是调一次和调多次这么简单吧。
提醒:接下来的内容比较重要,有点抽象但需要理解透彻
案例:假设我们需要每隔一秒控制台输出一句话。
结合我们本文的学习,给出思路:
1、一次性定时器的函数里再调定时器,形成循环。
2、开启一个重复性定时器
编写实现代码:
思路1:
setTimeout(function run(name,gender){
console.log(" hello");
setTimeout(run,1000);
}, 1000);
思路2:
setInterval(()=>{
console.log("hello")
},1000);看到这大家可能会不禁感叹,就这?就这?这哪复杂了,逗我呢。
那不妨思考一下,第二个一次性定时器啥时候开始执行呢?第三个呢?第n个呢?程序运行的第n秒?
那我稍微改造一下刚刚的案例好了
let start = Date.now(); // 程序一运行的时间
let times = []; // 用来记录运行时间的数组
let sTime = setInterval(()=>{
times.push(Date.now() - start); // 记录下执行时间
if (start + 5000 < Date.now()) {
console.log(times);
}
},1000);接着可以思考一下输出的结果是什么。
然后再来思考重复性定时器,第二次函数调用是啥时候执行呢?第三个呢?第n个呢?
再稍微改造一下好了
let start = Date.now(); // 程序一运行的时间
let times = []; // 用来记录运行时间的数组
let sTime = setInterval(()=>{
times.push(Date.now() - start); // 记录下执行时间
if (start + 5000 < Date.now()) {
console.log(times);
}
},1000);好了,留些时间思考一下…
思考好了吗,好了的话一起揭晓一下答案吧。
第一种情况: > "1 ===>" > "2 ===>" > "1 ===>" > "2 ===>"
第二种情况: > Array [1001, 2003, 3003, 4000, 5000, 6000]
分析: 情况1:思考这个问题就可 -> 输出 "1 ===>" 之后我开启了另一个定时器,此时是不是应该再输出"1 ===>"?
然后就进入了定时器循环,结果一直只有"1 ===>"?
结合我们的结果,可以发现下一个定时器是什么时候开的?没错,执行完第一个定时器函数内的代码后再执行的。
情况2:根据时间的间隔很容易知道时间就是1秒上下几毫秒,所以下一个定时器是第一个定时器时间结束后立即开启的。
这就是他们两个比较靠底层的区别。
总结的话就留给大家自己总结吧,毕竟一千个读者就会有一千个读者(哈哈,开个玩笑,说句可能像话的话😄)。
定时器的取消与内存管理
现在我们已经大致了解了定时器以及触发时间,那么会造定时器了不会取消就有点说不过去了,下面一起看看怎么取消定时器。
let timerId1 = setTimeout(...);
clearTimeout(timerId1); // 取消一次性定时器,timeId1 是唯一且必传参数
let timerId2 = setInterval(...);
clearInterval(timerId2)。 // 取消重复定时器,timeId2 是唯一且必传参数注意:定时器开启了一定要关闭,要做到有始有终,不然会一直消耗内存,到时候就就很容易程序崩溃。
嵌套调用的最小延时限制
还有一个留最后讲的,因为比较细节。
下面我们来看个案例
let start = Date.now();
let times = [];
setTimeout(function run() {
times.push(Date.now() - start); // 保存前一个调用的延时
if (start + 50 < Date.now()) console.log(times); // 100 毫秒之后,显示延时信息
else setTimeout(run); // 否则重新调度
});
结果:
> Array [1, 2, 4, 5, 9, 13, 18, 22, 27, 32, 36, 42, 46, 50, 55]let start = Date.now(); // 程序一运行的时间
let times = []; // 用来记录运行时间的数组
let sTime = setInterval(()=>{
times.push(Date.now() - start); // 记录下执行时间
if (start + 50 < Date.now()) {
console.log(times);
clearInterval(sTime); // 清除定时器
}
});
结果:
> Array [1, 2, 3, 4, 8, 13, 16, 20, 25, 28, 32, 36, 40, 44, 48, 53]感兴趣的同学可以分别思考一下这两组数组的规律,然后再往下看
好了,这就不卖关子了,直接把结论告诉大家吧
浏览器会将 setTimeout 或 setInterval 的五层或更多层嵌套调用(调用五次之后)的最小延时限制在 4ms。这是历史遗留问题。
最后,大家拷贝案例执行的时候,运行的结果很大概率和我这个结果不一样,影响的因素有浏览器版本、类型等等问题。不过这也不影响结论是正确的
总结
到此这篇关于JavaScript定时器setTimeout、setInterval使用的文章就介绍到这了,更多相关定时器setTimeout、setInterval使用内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
