Skip to content

JavaScript 事件物件:target、currentTarget 與 type

事件物件:target、currentTarget 與 type

當任何的 事件 發生時,瀏覽器就會為這個事件創造一個物件,我們稱為 事件物件(Event Object)。它會提供額外資訊,依照事件類型的不同,會帶有不同的資料。在下方程式碼中,事件物件會以參數的形式傳給我們。

html
<div>
  <input id="Btn" type="button" value="我是按鈕">
</div>
js
document.querySelector('#Btn').addEventListener('click', (e) => {
  // e: 本身包含了所有事件共同的屬性及方法
  console.log(e);
});

小提醒

參數名稱寫 eevtevent 都可以,它只是個參數名;習慣上多寫 e。第一次接觸時,請直接 console.log(e) 展開看看裡面有什麼。

type

回傳一個代表此事件物件類型的字串。

html
<div>
  <input id="Btn" type="button" value="我是按鈕">
</div>
js
document.querySelector('#Btn').addEventListener('click', (e) => {
  // type: click
  console.log('type: ', e.type);
});

同一個函式要處理多個事件類型時,e.type 就能派上用場:

js
const elemBtn = document.querySelector('#Btn');

function handler(e) {
  console.log(e.type === 'mouseenter' ? '進來了' : '離開了');
}

elemBtn.addEventListener('mouseenter', handler);
elemBtn.addEventListener('mouseleave', handler);

target 與 currentTarget

以下將觸發的對象改為 <div>

html
<div id="Box">
  <input type="button" value="我是按鈕">
</div>
js
document.querySelector('#Box').addEventListener('click', (e) => {
  // 指向觸發的 DOM 物件,也就是 <input>
  console.log('target: ', e.target);

  // 指向監聽的 DOM 物件,也就是 <div>
  console.log('currentTarget: ', e.currentTarget);
});
屬性指向何時會不同
e.target實際觸發事件的元素點到子元素時
e.currentTarget掛上監聽器的元素同上

小提醒

這組差異就是 事件委派 能成立的關鍵:監聽器掛在父層(currentTarget),但我們真正想知道的是使用者點到哪個子元素(target)。

nodeName 與 tagName

如果只是處理元素,那麼使用 tagNamenodeName 沒有差別。

html
<div>
  <input id="Btn" type="button" value="我是按鈕">
</div>
js
document.querySelector('#Btn').addEventListener('click', (e) => {
  // tagName: INPUT
  console.log('tagName:', e.target.tagName);

  // nodeName: INPUT
  console.log('nodeName:', e.target.nodeName);
});

與上述的結果一樣沒有差別。

js
// tagName: INPUT
console.log('tagName:', document.querySelector('#Btn').tagName);

// nodeName: INPUT
console.log('nodeName:', document.querySelector('#Btn').nodeName);

若對象不是元素,就有差異性了。

js
// tagName: undefined
console.log('tagName:', document.tagName);

// nodeName: #document
console.log('nodeName:', document.nodeName);

總結

tagName 只能用在元素節點上,而 nodeName 可以用在任何 節點 上,可以說 nodeName 涵蓋了 tagName,並且具有更多的功能,因此,建議使用 nodeName

注意

兩者回傳的名稱都是 大寫,所以比對時要寫 e.target.nodeName === 'INPUT',寫成小寫的 input 永遠不會成立。

其他常用的屬性與方法

成員用途
e.key鍵盤事件中按下的按鍵,例如:Entera
e.clientX / e.clientY滑鼠相對於可視範圍的座標
e.currentTarget.value表單元素當下的值,常用在 inputchange
e.preventDefault()取消該元素的預設行為
e.stopPropagation()阻止事件繼續往外傳播

常見問題

事件物件是誰傳進來的?

瀏覽器。事件發生時瀏覽器會建立事件物件,並在呼叫事件處理器時把它當第一個參數傳進來,習慣上寫成 eevent

target 與 currentTarget 有什麼差別?

target 指向實際觸發事件的元素,也就是使用者真的點到的那個;currentTarget 指向掛上這個監聽器的元素。兩者在 事件委派 時通常不同。

nodeName 與 tagName 該用哪一個?

建議用 nodeNametagName 只能用在元素節點上,nodeName 適用於任何節點,涵蓋範圍更廣。兩者回傳的元素名稱都是大寫。

箭頭函式裡可以用事件物件嗎?

可以,而且建議這樣做。箭頭函式沒有自己的 this,取不到觸發事件的元素,此時就用事件物件的 targetcurrentTarget 代替。

事件物件還有哪些常用成員?

常用的有 key 取得按下的按鍵、clientXclientY 取得滑鼠座標、preventDefault() 取消預設行為,以及 stopPropagation() 阻止事件繼續傳播。

延伸閱讀