在JavaScript中,定时器是一种用于在指定时间间隔后执行代码或重复执行代码的机制,它主要用于处理异步任务,例如延迟执行、动画效果、轮询数据等,JavaScript提供了两种主要的定时器方法:setTimeout 和 setInterval,以及它们的清除方法 clearTimeout 和 clearInterval,现代JavaScript还引入了更精确的 requestAnimationFrame 方法,特别适用于动画场景。

setTimeout 方法
setTimeout 用于在指定的毫秒数后执行一次函数或代码片段,其基本语法如下:
let timerId = setTimeout(function() {
// 要执行的代码
}, delay);
function():定时器到期时执行的回调函数。delay:延迟的时间,单位为毫秒(1秒 = 1000毫秒)。timerId:返回的定时器ID,可用于清除定时器。
示例:
console.log("开始等待");
setTimeout(() => {
console.log("3秒后执行");
}, 3000);
console.log("等待中...");
输出顺序为:
开始等待
等待中...
3秒后执行
注意事项:

- 延迟时间不精确:
setTimeout的实际执行时间可能略长于指定的延迟,因为JavaScript是单线程的,定时器需要在当前代码执行完毕后才会被调度。 - 参数传递:可以通过匿名函数或箭头函数传递参数:
setTimeout((param1, param2) => { console.log(param1, param2); }, 1000, "参数1", "参数2");
setInterval 方法
setInterval 用于每隔指定的毫秒数重复执行函数或代码片段,其语法与 setTimeout 类似:
let intervalId = setInterval(function() {
// 要执行的代码
}, interval);
interval:重复执行的时间间隔,单位为毫秒。intervalId:返回的定时器ID,可用于清除定时器。
示例:
let count = 0;
let intervalId = setInterval(() => {
count++;
console.log("计数:" + count);
if (count >= 5) {
clearInterval(intervalId);
}
}, 1000);
输出:
计数:1
计数:2
计数:3
计数:4
计数:5
注意事项:

-
累积延迟问题:如果回调函数的执行时间超过间隔时间,可能会导致任务堆积。
setInterval(() => { console.log("开始"); // 假设这里有一个耗时2秒的操作 setTimeout(() => console.log("结束"), 2000); }, 1000);输出会重叠,因为每次执行间隔为1秒,但函数内部耗时2秒。
-
手动控制循环:推荐使用
setTimeout递归调用来模拟setInterval,以避免累积延迟:function repeat() { console.log("重复执行"); setTimeout(repeat, 1000); } repeat();
定时器的清除方法
clearTimeout:用于清除setTimeout创建的定时器。let timerId = setTimeout(() => console.log("不会执行"), 2000); clearTimeout(timerId);clearInterval:用于清除setInterval创建的定时器。let intervalId = setInterval(() => console.log("循环"), 1000); clearInterval(intervalId);
requestAnimationFrame 方法
requestAnimationFrame 是专门用于动画的定时器方法,它会在浏览器下一次重绘之前执行回调函数,通常与 cancelAnimationFrame 配对使用,其语法如下:
let animationId = requestAnimationFrame(callback);
callback:动画帧回调函数,接收一个时间戳参数。
示例:
function animate(timestamp) {
console.log(timestamp);
if (timestamp < 5000) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
优点:
- 更流畅的动画效果,因为与浏览器的重绘频率同步。
- 当页面不可见时(如切换标签页),会自动暂停以节省资源。
定时器的实际应用场景
| 应用场景 | 推荐方法 | 示例用途 |
|---|---|---|
| 延迟执行 | setTimeout |
用户操作后的延迟反馈(如提示框) |
| 重复任务 | setInterval |
定时更新数据、轮询服务器 |
| 动画 | requestAnimationFrame |
平滑的页面动画、游戏循环 |
| 防抖/节流 | setTimeout |
优化频繁触发的事件(如滚动、输入) |
常见问题与最佳实践
- 内存泄漏:未清除的定时器会导致回调函数无法被垃圾回收,可能引发内存泄漏,在不需要时应手动清除定时器。
- 定时器嵌套:避免在定时器中嵌套过深的回调,可能导致代码难以维护,可以使用
Promise或async/await优化异步逻辑。
相关问答FAQs
Q1: setTimeout 和 setInterval 有什么区别?
A1: setTimeout 只执行一次回调函数,而 setInterval 会按照固定间隔重复执行。setTimeout 的实际执行时间可能受主线程任务影响,而 setInterval 可能因回调执行时间过长导致任务堆积。
Q2: 如何确保定时器精确执行?
A2: JavaScript 定时器本身无法保证绝对精确,但可以通过以下方法优化:
- 使用
performance.now()记录时间戳,动态调整延迟。 - 对于高精度需求,结合
requestAnimationFrame和时间戳计算实现自定义循环。 - 避免在定时器中执行耗时操作,确保回调轻量化。
