Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

JavaScript 事件處理器:從輪詢到 addEventListener 的事件機制

最後更新:2026年3月3日JavaScript

使用者隨時可能點擊按鈕、按下鍵盤、或是捲動頁面。

而我們寫的 JavaScript 程式,要怎麼知道使用者做了這些操作,並且做出對應的反應?

這就是「事件處理」要解決的問題。

這篇文章會從最原始的做法開始,一步步帶你理解瀏覽器的事件處理機制。

最原始的做法:輪詢按鍵狀態

想像早期電腦的鍵盤,每個按鍵只有兩種狀態:0 代表沒有被按,1 代表正在被按。

你的程式去問鍵盤「這個鍵現在有沒有被按?」,得到的只是當下的答案,不是歷史紀錄。

問題在於,使用者按下一個鍵、然後放開,這個動作可能只持續幾十毫秒。

如果你的程式剛好在按鍵被按下的那一刻去問,會看到 1。

但只要晚一點點,按鍵已經放開了,你看到的就是 0,就好像什麼事都沒發生一樣。

也就是說,鍵盤不會主動告訴你「剛才有人按了某個鍵」,你唯一能做的就是自己不斷去問,盡量不要錯過那個時機。

這代表你的程式必須不斷地、重複地去問按鍵狀態,中間不能做太多其他事情。

一旦程式忙著執行其他計算,就有可能錯過按鍵被按下的那個瞬間。

這種做法既浪費資源,程式一旦忙起來也很容易漏掉使用者的操作。

改良做法:用佇列記錄事件

有些早期的機器採取了改良的做法。

它們把「盯著鍵盤」這件事交給硬體或作業系統來做,程式本身不需要一直守在那裡。

一旦有按鍵被按下,硬體或作業系統就會把這個事件記錄到一個「佇列」(queue)裡面。

佇列是一種資料結構,先記錄進去的事件會先被處理。

所以就算使用者在很短的時間內按了好幾個鍵,每個事件都會照順序排好,不會漏掉。

程式只要定期去檢查佇列裡有沒有新事件就好。

如果發現有事件,就做出對應的反應。

這樣比第一種做法好多了,但還是有問題。

程式仍然需要「主動」去檢查佇列,而且要夠頻繁。

從按鍵被按下,到程式真正注意到這個事件,中間有一段空窗期,在這段時間內軟體看起來就像沒有反應一樣。

輪詢(Polling):程式主動反覆去問

上面這兩種做法,不管是「不斷檢查按鍵狀態」還是「定期檢查佇列」,都屬於同一種模式,叫做輪詢(polling)。

輪詢的核心概念是:程式自己主動、反覆地去問「有事情發生嗎?有事情發生嗎?」

大多數時候去問的結果都是「沒有事件」,但這些問題還是消耗了 CPU 的時間和資源。

另一個問題是反應速度。

輪詢的間隔越長,從事件發生到程式察覺的時間就越久,使用者會感覺到操作沒有立即回應。

但間隔越短,程式就要問得越頻繁,消耗的資源也越多。

這是一個兩難,沒有辦法同時做到既省資源又反應即時。

事件處理器:讓瀏覽器主動通知你

與其讓程式不斷去問「有事情發生嗎?」,更好的做法是反過來:事件發生的時候,由系統主動通知程式。

瀏覽器就提供了這種機制。

你可以預先告訴瀏覽器:「當使用者點擊按鈕的時候,請執行這個函式。」

這個動作叫做「註冊事件處理器(register event handler)」。

什麼是「註冊」?

「註冊」就是事先登記的意思。

你的程式在執行時,瀏覽器並不知道你之後想對哪些操作做出反應,所以你需要事先告訴它:「如果這件事發生了,請執行這段程式碼。」

瀏覽器內部有一張清單,叫做 Event Listener List。

當你執行註冊這個動作,就是把你的函式寫進這張清單裡。

之後每當事件發生,瀏覽器就會查這張清單,找到對應的函式並執行它。

什麼是「事件」?

「事件」是所有使用者操作與系統狀態變化的統稱。

點擊只是其中一種,按下鍵盤、捲動頁面、網頁載入完成、網路斷線,這些全部都叫做事件。

什麼是「處理器」?

「處理器」指的就是你寫的那個函式。

在 JavaScript 裡,處理器確實就是一個 function,但我們不直接叫它「函式」,是因為「函式」只描述了它的語法形式,沒有說明它的用途。

「處理器」這個名稱,強調的是它的職責:負責應對(handle)某個事件。

有事件,就必須有對應的處理器,兩者是成對存在的。

整句話的邏輯是:「把一個負責應對事件的函式,登記到瀏覽器的監聽清單裡。」

與佇列做法的差別

註冊完之後,你的程式什麼都不用做。

不像佇列那個做法還需要定期去檢查,事件處理器是由瀏覽器在事件發生的當下直接呼叫你的函式。

這個被註冊的函式就叫做事件處理器(event handler)。

佇列記錄事件註冊事件處理器
誰在監聽硬體或作業系統瀏覽器
程式需要主動去問嗎要,定期去檢查佇列不用
事件發生時記錄到佇列,等程式來取瀏覽器直接呼叫你的函式
反應速度取決於檢查的頻率即時
佇列記錄事件硬體或作業系統
註冊事件處理器瀏覽器
佇列記錄事件要,定期去檢查佇列
註冊事件處理器不用
佇列記錄事件記錄到佇列,等程式來取
註冊事件處理器瀏覽器直接呼叫你的函式
佇列記錄事件取決於檢查的頻率
註冊事件處理器即時

用 addEventListener 註冊事件處理器

前面說到,你可以預先告訴瀏覽器:「當使用者點擊按鈕的時候,請執行這個函式。」

那在實際的程式碼裡,這件事要怎麼做到?

在瀏覽器中,addEventListener 就是用來執行「註冊」這個動作的方法。

它的名稱直接說明了它的用途:add(加入)+ event(事件)+ listener(監聽者,也就是你寫的那個事件處理器函式),意思是「把一個事件和對應的函式,登記到瀏覽器的監聽清單裡」。

還記得前面說的 Event Listener List 嗎?

那張清單記錄的是「哪個事件」對應「哪個函式」的配對關係。

執行 addEventListener,就是把這個配對寫進清單裡的動作。

先看一個簡單的例子:

<p>點擊這個頁面來觸發事件處理器。</p>
<script>
  window.addEventListener("click", () => {
    console.log("You knocked?");
  });
</script>

這段程式碼做了什麼事?

讓我們拆開來看。

指定監聽對象

window.addEventListener(...)

window 是瀏覽器提供的內建物件,代表整個瀏覽器視窗。

我們在 window 上面呼叫 addEventListener,意思是「我要在整個視窗上監聽事件」。

指定事件類型

window.addEventListener("click", ...)

第一個參數是事件的名稱,這裡是 "click",代表「滑鼠點擊」事件。

指定事件處理器函式

window.addEventListener("click", () => {
  console.log("You knocked?");
});

第二個參數是一個函式,這就是我們的事件處理器。

當點擊事件發生時,瀏覽器會自動呼叫 () => { console.log("You knocked?"); },在 console 印出 "You knocked?"。

整個過程用一句話來說就是:

把一個事件處理器函式註冊到 window 上,當 click 事件發生時,瀏覽器就會自動執行它。

小結

這篇文章介紹了程式處理事件的兩種方式:

  • 輪詢(polling):程式主動、反覆地去檢查有沒有事件發生,缺點是浪費資源且反應不夠即時。
  • 事件處理器(event handler):預先註冊一個函式,事件發生時由系統主動呼叫,是瀏覽器採用的機制。

在瀏覽器中,我們透過 addEventListener 來註冊事件處理器,它接收兩個參數:事件名稱和要執行的函式。

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

JavaScript

目錄

  • 最原始的做法:輪詢按鍵狀態
  • 改良做法:用佇列記錄事件
  • 輪詢(Polling):程式主動反覆去問
  • 事件處理器:讓瀏覽器主動通知你
  • 什麼是「註冊」?
  • 什麼是「事件」?
  • 什麼是「處理器」?
  • 與佇列做法的差別
  • 用 addEventListener 註冊事件處理器
  • 指定監聽對象
  • 指定事件類型
  • 指定事件處理器函式
  • 小結