⚡ 30 秒速记
- 核心判断:理解原理要建立输入、状态变化、输出和失败边界,而不是只记 API 与结论
- 原理主线:围绕 「核心机制」、「执行链路」、「边界与实践」 建立输入、状态变化与输出之间的因果关系
- 文章范围:介绍了JavaScript中setTimeout的用法、底层实现原理以及在浏览器中的工作机制,帮助开发者理解定时器的执行流程和注意事项。
- 边界与代价:文章中的实现通常有版本和场景前提,迁移到当前项目时必须先核对运行环境与依赖
- 工程落地:面试回答按核心机制、执行链路、边界反例和工程验证展开,最后说明取舍
setTimeout 设置的是回调进入可执行队列前的最短延迟,并不保证到点立即运行。 浏览器记录回调、创建时间和延迟时间,任务到期后仍要等主线程处理完当前任务,因此长任务会直接推迟执行。回调被单独传入时会丢失原对象的调用关系,this 通常不再指向原对象。工程上还要考虑多层嵌套后的 4ms 最小间隔、后台标签页的 1000ms 限制,以及约 24.8 天的延迟上限。
这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。
版本校准: 原理文章中的代码代表特定实现与写作时间。应用到当前项目时,应先确认浏览器、框架或工具的主版本,再区分稳定的规范语义、可变化的内部实现和项目自身约束。
setTimeout,它就是一个定时器,用来指定某个函数在多少毫秒之后执行
# setTimeout用法
var timeoutID = setTimeout(function[, delay, arg1, arg2, ...]);
var timeoutID = setTimeout(function[, delay]);
var timeoutID = setTimeout(code[, delay]);
- 第一个参数为函数或可执行的字符串(比如
alert('test'),此法不建议使用) - 第二个参数为延迟毫秒数,可选的,默认值为
0. - 第三个及后面的参数为函数的入参。
setTimeout的返回值是一个数字,这个值为timeoutID,可以用于取消该定时器
# setTimeout在浏览器中的实现
- 浏览器渲染进程中所有运行在主线程上的任务都需要先添加到消息队列,然后事件循环系统再按照顺序执行消息队列中的任务。
- 在 Chrome 中除了正常使用的消息队列之外,还有另外一个消息队列(我们可以称为延迟队列),这个队列中维护了需要延迟执行的任务列表,包括了定时器和 Chromium 内部一些需要延迟执行的任务。所以当通过 JavaScript 创建一个定时器时,渲染进程会将该定时器的回调任务添加到延迟队列中。