news 2026/2/15 3:29:29

JavaScript 定时器完全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript 定时器完全攻略

一、前言

在 JavaScript 中,定时器是实现延迟执行代码、周期性执行代码的核心工具,广泛应用于轮播图、倒计时、定时刷新数据等场景。本文将全面梳理 JS 定时器的核心用法、区别、注意事项及实战技巧,适合前端初学者巩固基础,也可作为开发中的参考手册。

二、JS 定时器的两种核心类型

JavaScript 提供了两种原生定时器方法,均挂载在window对象上(浏览器环境),无需额外引入依赖即可使用。

一次性定时器:setTimeout ()

延迟指定时间后,只执行一次指定的回调函数(或代码片段)。

// 语法1:传入回调函数lettimeoutId=setTimeout(callback,delay,[param1,param2,...]);

参数说明:

  • callback:必需,延迟后要执行的回调函数(无返回值)。

  • delay:可选,延迟时间,单位为毫秒(ms),默认值为0(注意:不是立即执行,后续会解释)。

  • [param1, param2, …]:可选,传递给回调函数的参数列表。

  • timeoutId:返回值,定时器的唯一标识(正整数),用于后续取消定时器。

周期性定时器:setInterval ()

每隔指定时间,重复执行指定的回调函数(或代码片段),直到主动取消或页面卸载。

letintervalId=setInterval(函数,时间)
  • 第一个参数传函数名,第二个参数是间隔时间,毫秒为单位

  • intervalId:返回值,定时器的唯一标识(正整数),用于后续取消定时器。

三、取消定时器:清除已创建的定时器

定时器创建后,可通过其返回的唯一标识(timeoutId/intervalId)取消执行,避免不必要的性能消耗。

  • 取消一次性定时器:clearTimeout(timeoutId)
  • 取消周期性定时器:clearInterval(intervalId)
letn=setInterval(function(){i--btn.innerHTML=`我已经阅读用户协议(${i})`if(i===0){clearInterval(n)btn.disabled=falsebtn.innerHTML=`同意`}},1000)

已取消的定时器标识无法再复用,若需重新执行定时器,需重新调用setTimeout()/setInterval()并获取新标识。

四、关键理解:定时器的延迟时间不是绝对的

很多初学者会疑惑:为什么设置delay=1000,但函数不是恰好 1 秒后执行?
核心原因:JavaScript 是单线程语言,定时器的回调函数需要等待主线程空闲后才能执行。

  1. 当调用setTimeout()/setInterval()时,JS 引擎会将定时器回调函数放入定时器队列,并开始计时。
  2. 当delay时间到达后,回调函数并不会立即执行,而是会被移入任务队列(宏任务队列)。
  3. JS 主线程遵循 “事件循环(Event Loop)” 机制,只有当主线程当前的同步代码执行完毕,且任务队列中没有其他更早的宏任务时,才会从任务队列中取出回调函数执行。
  4. 因此,若主线程被耗时的同步代码(如复杂循环、大型计算)阻塞,回调函数的执行时间会大于等于delay设定的时间。

五、setInterval () 的潜在问题:回调执行重叠(及解决方案)

  • 潜在问题:回调执行重叠
    setInterval()的设计缺陷:它会按照固定的时间间隔将回调函数推入任务队列,不关心上一次的回调函数是否已经执行完毕。
  • 若上一次回调函数执行耗时超过delay设定的时间间隔,下一次回调函数已经被推入任务队列,会导致多个回调函数连续执行(即 “执行重叠”)。
  • 长期运行可能导致内存泄漏、页面卡顿,尤其在处理网络请求、DOM 操作等耗时操作时风险更高。

2.解决方案:嵌套 setTimeout () 实现可靠的周期性执行

  • 通过在setTimeout()的回调函数中重新调用自身,实现周期性执行,优势是确保上一次回调函数完全执行完毕后,再开始下一次计时,避免执行重叠。
// 嵌套setTimeout()实现周期性执行(推荐)functionperiodicTask(){// 1. 执行核心业务逻辑letnow=newDate().toLocaleTimeString();console.log("当前时间:",now);// 2. 上一次任务执行完毕后,延迟1秒再开启下一次任务setTimeout(periodicTask,1000);}// 启动周期性任务periodicTask();// 如需取消,可保存定时器标识并调用clearTimeout()lettaskId;functioncancelPeriodicTask(){clearTimeout(taskId);console.log("周期性任务已取消");}

相比setInterval(),嵌套setTimeout()的执行间隔是 “上一次任务结束到下一次任务开始” 的间隔,更可控。
避免了回调重叠问题,适合执行耗时不确定的周期性任务(如定时请求接口获取数据)。
核心作用

  • 实现 “异步执行”,将耗时较短的任务推迟到同步代码执行完毕后执行,避免阻塞主线程。
  • 常用于调整代码执行顺序,例如:优先执行同步 DOM 操作,再执行后续的逻辑处理。

六、总结

  1. JS 定时器有两种核心类型:一次性setTimeout()(只执行一次)、周期性setInterval()(重复执行)。
  2. 取消定时器对应clearTimeout()和clearInterval(),需依赖定时器返回的唯一标识。
  3. 定时器的延迟时间是 “最小延迟”,而非 “绝对延迟”,受单线程事件循环机制影响。
  4. setInterval()存在回调重叠风险,推荐使用嵌套setTimeout()实现可靠的周期性执行。
  5. setTimeout(callback, 0)用于将任务推迟到同步代码执行完毕后执行,实现异步插队。
  6. 开发中需注意及时清除定时器、处理this指向、避免传入字符串回调等避坑点。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/14 1:20:49

day132—链表—K个一组翻转链表(LeetCode-25)

题目描述给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节点内部…

作者头像 李华
网站建设 2026/2/12 4:37:23

【毕业设计】基于Java的学生身体素质测评管理系统基于SpringBoot的学生身体素质测评管理系统(源码+文档+远程调试,全bao定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/2/3 23:47:48

【信号处理】通过 “最近邻匹配” 和 “球面线性插值(SLERP)” 两种方式将 GNSS 位姿(位置 + 四元数)插值到激光雷达时间戳附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和数学建模资料 &#x1f34…

作者头像 李华
网站建设 2026/2/10 9:50:50

计算机毕设 java 基于协同过滤算法的就业推荐系统的设计与实现 基于协同过滤算法的智能就业推荐平台 求职与企业招聘匹配系统

计算机毕设 java 基于协同过滤算法的就业推荐系统的设计与实现(配套有源码、程序、MySQL 数据库、论文),本套源码可先查看功能演示视频,文末有联xi 可分享c系统核心功能涵盖注册登录、个人中心、多角色管理(管理员、用…

作者头像 李华