📚

JavaScriptのEvent.targetとEvent.currentTargetについて

に公開
1

はじめに

JavaScriptのイベントが発生した際の要素の取得において、targetとcurrentTargetで異なる挙動をすることがわかったので記事にまとめました。

targetとcurrentTargetの違いについて

以下のサンプルコードで、取得できる要素についての違いを確認してみます。

<section>
  <div>
    <button>Click</button>
    <div class="count-state">0</div>
  </div>
</section>
let count = 0;

function countUp(): void {
  const section = document.querySelector<HTMLElement>("section");
  const displayCount = document.querySelector<HTMLDivElement>(".count-state");
  if (!section || !displayCount) return;

  section.addEventListener("click", (e) => {
    count += 1;
    displayCount.textContent = String(count);
    console.log("target:", e.target);
    console.log("currentTarget:", e.currentTarget);
  });
}

document.addEventListener("DOMContentLoaded", countUp);

上記のコードで出力される結果は以下です。

console.log("target:", e.target);
// target: <button>Click</button>

console.log("currentTarget:", e.currentTarget);
// currentTarget: <section>...<section>

targetはbutton要素が出力され、currentTargetはsection要素が出力されました。
その理由は、targetがイベント発生元の要素を取得して、currentTargetはイベントリスナーが紐づいている要素を常に取得しているからです。
今回のケースでは、変数sectionに対してaddEventListenerを設定しているためcurrentTargetは変数sectionで参照している要素を取得することになります。

上記の理解をするにはイベントのバブリングについても知っておく必要があります。
以下のサイトで詳しく説明がされていますが簡単にまとめると、ターゲット要素でイベントが発生した後、親要素→さらに上位の要素へと順番に伝播していくイメージです。
イベントバブリングについて

上記のサンプルコードでは以下の流れです。

<button>要素でイベント発生
↓
<div>要素に伝播
↓
<section>要素に伝播(親要素がないため、伝播は終了)

特定のタイミングでイベントバブリングを終了させたい場合は、stopPropagation()を使用します。

まとめ

イベントが発生した際の要素の取得において、targetとcurrentTrargetでは対象が異なる。
targetはイベントが発生した要素を取得するためユーザーの操作によって都度変わってしまう可能性がある。
currentTargetはイベントリスナーが紐づいている要素を取得するので、返却される要素は変わらない。

参考サイト

Discussion

junerjuner

targetはイベントが発生した要素を取得するためユーザーの操作によって都度変わってしまう可能性がある。

むしろそういうときこそ closest() メソッドですよ感あります。

自身またはその親の系列にそのセレクタ対象の要素が居た場合にその要素を返すのでとても便利です。

https://developer.mozilla.org/ja/docs/Web/API/Element/closest