JavaScript加强篇——第六章 定时器(延时函数)与JS执行机制
目录
一、定时器函数
二、JavaScript 执行机制
三、同步与异步任务
四、事件循环原理
摘要:本文系统讲解了JavaScript定时器与执行机制,主要包含四个部分:1)定时器函数对比(setTimeout单次执行与setInterval重复执行)及使用示例;2)JS单线程特性引发的异步处理需求;3)同步与异步任务执行差异(同步阻塞、异步不阻塞);4)事件循环原理(执行栈、WebAPI、任务队列的协同工作)。重点指出:定时器是异步操作,即使延迟0ms也会在同步代码后执行;事件循环机制保证了单线程环境下的非阻塞执行。文章最后提供了高频面试题解答和记忆口诀。
一、定时器函数
两种定时器对比
类型 | 函数 | 执行特点 | 清除方法 | 应用场景 |
---|---|---|---|---|
延时函数 | setTimeout() | 执行一次后停止 | clearTimeout() | 广告弹窗延迟关闭 |
间歇函数 | setInterval() | 重复执行直到手动清除 | clearInterval() | 轮播图自动切换 |
代码示例
// 1. 延时函数(3秒后执行)
const timer1 = setTimeout(() => {console.log('3秒后执行');
}, 3000);// 清除延时(在3秒前调用可阻止执行)
// clearTimeout(timer1);// 2. 间歇函数(每秒执行)
let count = 0;
const timer2 = setInterval(() => {count++;console.log(`已执行 ${count} 次`);if(count >= 5) {clearInterval(timer2); // 5次后停止}
}, 1000);
⚠️ 关键注意事项
-
定时器时间单位为毫秒(1000ms = 1s)
-
定时器是异步操作,不会阻塞后续代码执行
-
定时器ID需保存以便清除
二、JavaScript 执行机制
单线程本质
JavaScript 是单线程语言,同一时间只能执行一个任务
为什么需要单线程?
单线程问题与解决方案
问题 | 解决方案 |
---|---|
长时间任务阻塞页面渲染 | 异步任务+事件循环 |
无法充分利用多核CPU | Web Worker(多线程) |
三、同步与异步任务
对比解析
特性 | 同步任务 | 异步任务 |
---|---|---|
执行顺序 | 顺序执行,前一个完成才执行后一个 | 不阻塞主线程,后续代码可立即执行 |
执行位置 | 主线程执行栈 | 任务队列等待执行 |
典型示例 | console.log() 、循环计算 | setTimeout 、click 事件 |
类比 | 排队点餐(一人点完才轮到下一个) | 扫码点餐(点完可做其他事) |
代码执行分析
console.log(1111); // 同步任务1
setTimeout(() => { // 异步任务console.log(2222); // 回调函数
}, 0); // 即使延迟0ms也是异步
console.log(3333); // 同步任务2/* 输出顺序:
1111
3333
2222
*/
❗ 重要结论
所有异步任务都需要回调函数支持
即使延迟时间为0ms,setTimeout
仍是异步任务
四、事件循环原理
执行流程
核心组件说明
-
执行栈
-
存放当前正在执行的同步任务
-
LIFO(后进先出)结构
-
-
Web API
-
浏览器提供的异步处理模块
-
包含:
-
Timer模块(
setTimeout
/setInterval
) -
DOM事件模块(
click
/scroll
等) -
网络请求模块(AJAX)
-
-
-
任务队列
-
存放已完成的异步任务回调
-
多个队列按优先级执行(微任务>宏任务)
-
-
事件循环
-
持续检查执行栈是否为空
-
当执行栈为空时,从任务队列取任务推入执行栈
-
完整执行流程
-
所有同步任务进入执行栈顺序执行
-
遇到异步任务交给Web API处理
-
Web API处理完成后将回调推入任务队列
-
当执行栈清空后,事件循环将任务队列中的回调推入执行栈执行
-
重复步骤1-4形成循环
✅ 核心要点总结
📝 高频面试题速答
-
Q:setTimeout(fn, 0) 为什么在同步代码后执行?
A:即使延迟0ms,setTimeout仍是异步任务,需等待同步任务执行完
-
Q:JavaScript为什么是单线程?
A:为避免DOM操作冲突(如同时添加删除同一元素)
-
Q:事件循环的基本原理?
A:持续检查执行栈是否为空,空时从任务队列取任务执行
-
Q:同步和异步任务的区别?
A:同步任务阻塞后续代码,异步任务不阻塞主线程
-
Q:如何清除间歇定时器?
A:使用clearInterval()并传入定时器ID
🧠 记忆口诀
"一栈二列三循环,同步先行异步随"
一栈:执行栈处理同步任务
二列:任务队列存放异步回调
三循环:事件循环连接两者