在學 JavaScript 的過程中,處理使用者互動是很重要的一環。
無論是點擊按鈕、輸入文字,甚至是滑鼠滑過畫面,這些行為在網頁上都被稱為「事件」。
而當你透過 JavaScript 捕捉這些事件時,總會收到一個 event 物件,而其中最常用、也最關鍵的屬性之一就是 event.target。
但這個屬性到底是什麼?為什麼它可以讓我們知道「使用者點了誰」?它又和我們熟知的 JavaScript 物件有什麼關係?本文將從零開始,帶你理解這一切。
event.target 是什麼?
當使用者觸發事件(例如點擊、輸入等)時,JavaScript 會自動將該事件的詳細資訊打包成一個 event 物件傳進你的處理函式中。
這個物件裡包含了許多資料,而其中的 target 屬性,就是指向當下被使用者實際操作的那個元素。
✅ 範例
<button>點我</button>
document.querySelector("button").addEventListener("click", function (event) {
console.log(event.target); // 👉 被點擊的那顆按鈕
});
這段程式中,當你點下按鈕,event.target 就會是那顆 <button> 元素。
event.target 是什麼型別?
你可能會好奇,這個 event.target 是什麼型別的資料?是字串嗎?還是函式?
答案是:它是一個 DOM 元素物件。
也就是說,它的型別是 HTMLElement 或 Element,根據實際觸發事件的 HTML 元素而定。
你可以把它想像成 JavaScript 中的一個物件,但這個物件是代表畫面上的某個 HTML 元素,並具備許多操作功能。
🔹為什麼 HTML 會變成 JavaScript 的物件?
這裡就得提到一個核心觀念:DOM(Document Object Model)。
當瀏覽器載入一份 HTML 文件時,會自動把 HTML 的內容「轉換成一棵物件樹」,這棵樹就叫做 DOM。這棵 DOM 樹中,每個 HTML 元素都會被變成一個可以用 JavaScript 操作的物件,也就是我們常說的 DOM 元素。
所以,當你在 JavaScript 中這樣寫:
const el = document.getElementById("greeting");即使原本只是這樣一段 HTML:
<p id="greeting">哈囉</p>
el 就會是一個物件。你可以像操作一般 JavaScript 物件一樣操作它:
el.textContent = "你好,世界";
el.style.color = "red";
el.setAttribute("data-type", "info");
這一切就是因為瀏覽器已經幫我們把 HTML 結構轉成了 JavaScript 能操作的 DOM 結構
回到 event.target:既然是 DOM 元素,那它能做什麼?
因為 event.target 是一個 DOM 元素,所以它具備許多實用的屬性與方法,像是:
.tagName:取得元素的標籤名稱(如 “BUTTON”).id、.classList:操作元素的屬性與類別.textContent:取得或改變文字內容.style:修改元素樣式.setAttribute():設定 HTML 屬性
你可以用這段程式驗證它的型別與功能:
document.querySelector("button").addEventListener("click", function (event) {
console.log(typeof event.target); // "object"
console.log(event.target instanceof HTMLElement); // true
console.log(event.target.tagName); // "BUTTON"
});
🔹 5. 那 .value 和 .name 呢?什麼時候會出現在 event.target 上?
在你使用 event.target 時,常會看到人們讀取 .value 和 .name 屬性,但這兩個屬性並不是每個 DOM 元素都有。它們只存在於「表單元素」上。
✅ 有 .value 和 .name 的情況
<input type="text" name="username" placeholder="輸入名字" />
document.querySelector("input").addEventListener("input", function (event) {
console.log(event.target.name); // "username"
console.log(event.target.value); // 使用者輸入的文字
});
這是因為 <input>、<select>、<textarea> 等元素在 DOM 中都有 .value 和 .name 這些屬性,是瀏覽器內建提供的。
❌ 沒有 .value 的情況
如果你點到的是一般元素,例如:
<div id="box" name="testBox">我是區塊</div>
document.getElementById("box").addEventListener("click", function (event) {
console.log(event.target.name); // "testBox"(有設定 name 才會有)
console.log(event.target.value); // undefined(div 沒有 value 屬性)
});
在這種情況下,.value 就是 undefined,因為 <div> 並不是一個可以「輸入內容」的元素。
HTML 沒寫 value 屬性,為什麼 .value 還是存在?
這也是初學者常見的疑問:我明明沒在 HTML 裡面寫 value="...",為什麼 JavaScript 還是可以存取 .value?
答案在於:DOM 中的 .value 屬性和 HTML 裡的 value 屬性是兩回事。
<input type="text" name="username" />
const input = document.querySelector("input");
console.log(input.value); // ""(一開始是空字串)
input.value = "Hello!";
console.log(input.value); // "Hello!"
即使你沒寫 value="...",.value 屬性依然存在,並預設為空字串。它表示「目前的輸入值」,而不是 HTML 載入時的預設值。
🧠 .value(屬性) vs value="..."(HTML 屬性)
| 項目 | .value(JS) | value="..."(HTML) |
|---|---|---|
| 設定位置 | JavaScript / DOM | HTML 原始碼 |
| 表示什麼 | 使用者目前輸入的內容 | 頁面初次載入時的預設值 |
| 是否會被同步更新? | ❌ 不會 | 需手動用 .setAttribute() 修改 |
這也說明了為什麼你會看到:
input.value = "新的值";
input.getAttribute("value"); // 仍然是原本的預設值
event.target 與 event.currentTarget 的差異
在事件處理中,event.target 和 event.currentTarget 是兩個看起來很像、但用途完全不同的屬性。
許多初學者一開始學事件監聽時常常混淆這兩者,理解清楚這個差異,對撰寫乾淨且可維護的互動邏輯非常重要。
📌 event.target 是「被點到的那個元素」
當使用者觸發一個事件時,真正觸發的那個元素,會被放在 event.target 中。它代表的是「事件源頭」,也就是畫面上使用者實際互動的那個元素。
📌 event.currentTarget 是「你綁定監聽器的元素」
而 event.currentTarget 則是指「事件監聽器所在的元素」。換句話說,它是你寫 addEventListener() 的那個 DOM 節點——不管使用者點到的是這個元素本身,還是它的子元素,currentTarget 永遠是你加監聽器的地方。
實際範例
假設你有以下 HTML 結構:
<ul id="menu">
<li>首頁</li>
<li>關於我們</li>
<li>聯絡方式</li>
</ul>
你在 <ul> 元素上綁定了一個點擊事件監聽器:
document.getElementById("menu").addEventListener("click", function (event) {
console.log("event.target:", event.target); // 點到哪一個 <li>
console.log("event.currentTarget:", event.currentTarget); // 永遠是 <ul>
});
🧪 假設你點了「關於我們」
event.target會是那個被點到的<li>(裡面顯示「關於我們」)event.currentTarget則仍然是整個<ul>,因為監聽器是綁在#menu上的
這種寫法就是所謂的「事件委派(event delegation)」:你只在父層 <ul> 綁定事件,但卻能捕捉到底是哪一個 <li> 被點了。
🧠 為什麼會有這兩個屬性?
因為事件在瀏覽器裡是「冒泡」的。
當你點擊某個子元素時,事件不只會在那個元素觸發,還會一層一層往上傳遞到父元素,最終傳到整個 document。而 event.currentTarget 就是用來讓你知道這段程式碼實際是在哪一層被呼叫的。
比較表一覽
| 屬性名稱 | 說明 |
|---|---|
event.target | 實際觸發事件的元素(被點到的那個元素) |
event.currentTarget | 綁定事件監聽器的元素(你加 .addEventListener 的那個) |
🎯 使用建議
- 如果你需要知道「使用者點了哪一個項目」,就用
event.target - 如果你只想針對「我在哪裡加了監聽器」做事情,就用
event.currentTarget - 在實作事件委派(event delegation)時,兩者通常會一起用
✅ 範例應用:只處理被點到的 <li>,其他忽略
document.getElementById("menu").addEventListener("click", function (event) {
if (event.target.tagName === "LI") {
console.log("你點的是:", event.target.textContent);
}
});
這樣做的好處是:你只需要在 <ul> 上加一次監聽器,就能處理所有 <li> 的點擊事件,未來如果有新的 <li> 被動態加入也不用重新加監聽器。
event.target 的實作應用:實用又彈性的互動處理技巧
理解了 event.target 的概念之後,接下來我們要看看它在實務開發中的應用。
這裡會介紹兩個常見場景,分別是「表單輸入變更監聽」與「多按鈕點擊處理」,你會發現 event.target 能讓事件處理更靈活、更簡潔。
範例 1:即時監聽使用者輸入內容
表單欄位(如 <input>)是最常與使用者互動的地方,而 event.target 可以幫我們即時取得使用者正在輸入的內容。
📌 HTML:
<input type="text" name="username" placeholder="輸入名字" />
📌 JavaScript:
document.querySelector("input").addEventListener("input", function (event) {
console.log("你輸入了:", event.target.value);
});
💡 解說:
- 當使用者在輸入框中打字,每打一個字就會觸發一次
input事件。 event.target就是那個<input>元素。.value是使用者輸入的內容,即時變化。
這種寫法適用於表單驗證、搜尋提示(autocomplete)、即時表單儲存等功能。
範例 2:多個按鈕共用一個事件監聽器
你有一組功能按鈕,例如「新增」、「編輯」、「刪除」,如果每個都加上 addEventListener(),不但麻煩,還會降低效能。這時就可以利用「事件委派(event delegation)」搭配 event.target 一次搞定!
📌 HTML:
<div id="btn-group">
<button>新增</button>
<button>編輯</button>
<button>刪除</button>
</div>
📌 JavaScript:
document.getElementById("btn-group").addEventListener("click", function (event) {
if (event.target.tagName === "BUTTON") {
console.log("你點的是:", event.target.textContent);
}
});
💡 解說:
- 事件監聽器只綁在父層
#btn-group。 - 透過
event.target判斷被點擊的是哪個<button>。 - 這就是事件委派:由父層統一處理子元素的事件。
使用 event.target 的最佳實踐
event.target 非常強大,但若使用不當也可能導致程式碼難以維護或效能低落。以下是幾個重要的實作建議:
一定要確認元素類型再操作
因為事件可能來自父層或其他元素,操作之前務必判斷 event.target 是你預期的那個元素類型。常見做法有:
if (event.target.tagName === 'BUTTON') { ... }
if (event.target.classList.contains('submit')) { ... }
這能避免誤操作,讓邏輯更明確、安全。
事件監聽器盡量綁在容器上,用 event.target 區分
這就是事件委派的原則。比起每個按鈕都各自加一個監聽器,更推薦這樣做:
document.querySelector("#container").addEventListener("click", (event) => {
if (event.target.matches(".action-btn")) {
// 統一處理所有具有 action-btn 類別的按鈕
}
});
這種做法的優點是:
- 容易維護
- 可支援動態加入的按鈕
- 效能更佳(監聽器數量少)
不要對每個小元素都加監聽器
這樣做雖然「當下直觀」,但會造成:
- 效能浪費(監聽器數量暴增)
- 不好維護(HTML 改動時 JS 也要同步改)
- 無法支援動態生成元素(像是 Ajax 或
appendChild產生的元素)
改用事件委派+event.target,是更理想的策略。
總結
| 重點 | 說明 |
|---|---|
event.target | 被操作的「實際元素」 |
| 典型應用 | 點擊按鈕、輸入欄、事件委派、動態 DOM 元素辨識 |
與 currentTarget 比較 | currentTarget 是「誰綁監聽器」,target 是「誰被點」 |
掌握 event.target,你就能寫出更聰明、更有彈性的事件處理邏輯,無論是製作互動元件、表單驗證,還是實作拖曳、動態清單等功能,都會事半功倍!