紅寶書第十六講:通俗詳解JavaScript回調(diào)函數(shù)與事件循環(huán)


紅寶書第十六講:通俗詳解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ù)。其核心流程如下:

  1. 執(zhí)行同步任務(wù)(立即執(zhí)行)
  2. 處理異步任務(wù)(如定時(shí)器、網(wǎng)絡(luò)請(qǐng)求)
  3. 任務(wù)隊(duì)列保存已完成的異步回調(diào)
  4. 輪詢隊(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)(如 setTimeoutfetch 的完成回調(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í)行順序解析

  1. 執(zhí)行所有同步代碼
  2. 清空微任務(wù)隊(duì)列(Promise回調(diào)優(yōu)先)
  3. 處理宏任務(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


腳注


  1. 《JavaScript高級(jí)程序設(shè)計(jì)(第5版)》說明DOM變化的回調(diào)機(jī)制 ? ?

  2. 《JavaScript高級(jí)程序設(shè)計(jì)(第5版)》展示異步操作的微任務(wù)優(yōu)先級(jí) ? ? ?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容