紅寶書第十六講:通俗詳解JavaScript回調(diào)函數(shù)與事件循環(huán)
資料取自《JavaScript高級(jí)程序設(shè)計(jì)(第5版)》。
查看總目錄:紅寶書學(xué)習(xí)大綱
一、回調(diào)函數(shù):任務(wù)的“代金券”
回調(diào)函數(shù)是將一個(gè)函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù),在特定條件滿足時(shí)自動(dòng)觸發(fā)執(zhí)行的機(jī)制。例如:用戶點(diǎn)擊按鈕時(shí)觸發(fā)函數(shù)、異步請(qǐng)求完成時(shí)處理數(shù)據(jù) [1]。
示例:DOM事件回調(diào)
// 點(diǎn)擊按鈕時(shí)觸發(fā)回調(diào)函數(shù)
const button = document.querySelector('#myButton');
button.addEventListener('click', function() {
console.log('按鈕被點(diǎn)擊了!');
});
[1]: 參考資料3指出Observer API使用回調(diào)函數(shù)響應(yīng)DOM變化
二、事件循環(huán):JavaScript的“調(diào)度中心”
JavaScript是單線程的,通過事件循環(huán)(Event Loop) 管理異步任務(wù)。其核心流程如下:
- 執(zhí)行同步任務(wù)(立即執(zhí)行)
- 處理異步任務(wù)(如定時(shí)器、網(wǎng)絡(luò)請(qǐng)求)
- 任務(wù)隊(duì)列保存已完成的異步回調(diào)
- 輪詢隊(duì)列,當(dāng)主線程空閑時(shí)按順序執(zhí)行回調(diào)
flowchart LR
SyncCode["同步代碼"] --> CallStack["調(diào)用棧"]
AsyncTask["異步任務(wù)"] --> WebAPI["Web APIs處理"]
WebAPI --> TaskQueue["完成時(shí)放入任務(wù)隊(duì)列"]
CallStack --> IsEmpty["調(diào)用棧是否為空?"]
IsEmpty -- "是" --> GetCallback["任務(wù)隊(duì)列取回調(diào)"]
GetCallback --> CallStack
關(guān)鍵概念:
- 調(diào)用棧(Call Stack):存放當(dāng)前執(zhí)行的函數(shù)
-
任務(wù)隊(duì)列(Task Queue):存放待處理回調(diào)(如
setTimeout、fetch的完成回調(diào)) -
微任務(wù)隊(duì)列(Microtask Queue):存放
Promise回調(diào),優(yōu)先級(jí)更高 [2]
[2]: 參考資料6展示異步操作通過Promise鏈?zhǔn)交卣{(diào)進(jìn)入微任務(wù)隊(duì)列
三、從代碼看事件循環(huán)
console.log('開始'); // 同步任務(wù) → 立即執(zhí)行
setTimeout(() => console.log('定時(shí)器回調(diào)'), 0); // 異步任務(wù) → 宏任務(wù)隊(duì)列
Promise.resolve().then(() => console.log('Promise回調(diào)')); // 異步任務(wù) → 微任務(wù)隊(duì)列
console.log('結(jié)束'); // 同步任務(wù) → 立即執(zhí)行
// 輸出順序:
// 開始 → 結(jié)束 → Promise回調(diào) → 定時(shí)器回調(diào)
執(zhí)行順序解析:
- 執(zhí)行所有同步代碼
- 清空微任務(wù)隊(duì)列(Promise回調(diào)優(yōu)先)
- 處理宏任務(wù)隊(duì)列(定時(shí)器、事件回調(diào))
四、回調(diào)函數(shù)的進(jìn)階應(yīng)用
結(jié)合異步操作(如 fetch 請(qǐng)求)處理數(shù)據(jù):
// 使用fetch發(fā)起異步請(qǐng)求,通過.then()注冊(cè)回調(diào)
fetch('https://api.example.com/data')
.then(response => response.json()) // 微任務(wù)
.then(data => console.log('數(shù)據(jù)獲取成功:', data))
.catch(error => console.error('請(qǐng)求失敗:', error));
[2]: 參考資料6演示通過異步回調(diào)鏈?zhǔn)教幚矸謮K數(shù)據(jù)
目錄:總目錄
上篇文章:紅寶書第十五講:詳解JavaScript迭代器與生成器:Symbol.iterator與yield
腳注
-
《JavaScript高級(jí)程序設(shè)計(jì)(第5版)》說明DOM變化的回調(diào)機(jī)制 ? ?
-
《JavaScript高級(jí)程序設(shè)計(jì)(第5版)》展示異步操作的微任務(wù)優(yōu)先級(jí) ? ? ?