0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】addEventListenerメソッドにおける「this」の挙動を理解する

Posted at

はじめに

JavaScriptでイベント処理を実装する際、addEventListenerメソッドは欠かせない存在です。しかし、このメソッド内でのthisの挙動は初学者にとって混乱しやすいポイントの一つです。

本記事では、addEventListenerにおけるthisの挙動について、具体例を交えながら解説していきます。

addEventListenerでのthisの基本

addEventListenerにイベントハンドラとして通常の関数を渡した場合、関数内のthisはイベントが発生した要素(イベントターゲット)を参照します。

const button = document.querySelector('#myButton');

button.addEventListener('click', function() {
  console.log(this); // <button id="myButton">が出力される
  console.log(this === button); // true
});

この挙動は、イベントハンドラ内で対象要素のプロパティやメソッドに直接アクセスできるため便利です。

通常の関数とアロー関数での違い

thisの挙動は、使用する関数の種類によって大きく異なります。

通常の関数の場合

通常の関数では、thisはイベントが発生した要素を指します。

const button = document.querySelector('#myButton');

button.addEventListener('click', function() {
  console.log(this); // buttonを参照
  this.textContent = 'クリックされました'; // 要素のテキストを変更できる
});

アロー関数の場合

アロー関数では、thisは定義された時点でのスコープのthisを継承します。イベントターゲットを参照しません。

const button = document.querySelector('#myButton');

button.addEventListener('click', () => {
  console.log(this); // windowオブジェクトまたは外側のスコープのthisを参照
  // this.textContent = '...' とすると期待通りに動作しない
});

以下の図で、それぞれのthisがどこを参照するかを視覚化してみましょう。

実際の使用例

パターン1: 要素自身を操作したい場合

要素自身のスタイルやテキストを変更したい場合は、通常の関数が適しています。

const buttons = document.querySelectorAll('.toggle-button');

buttons.forEach(button => {
  button.addEventListener('click', function() {
    // thisで直接要素にアクセス
    this.classList.toggle('active');
    this.textContent = this.classList.contains('active') 
      ? 'ON' 
      : 'OFF';
  });
});

パターン2: 外側のスコープにアクセスしたい場合

クラスのメソッドやオブジェクトのプロパティにアクセスしたい場合は、アロー関数が便利です。

class Counter {
  constructor() {
    this.count = 0;
    this.button = document.querySelector('#countButton');
    this.display = document.querySelector('#countDisplay');
    
    // アロー関数で外側のthis(Counterインスタンス)を参照
    this.button.addEventListener('click', () => {
      this.count++; // Counterインスタンスのcountにアクセス
      this.display.textContent = this.count;
    });
  }
}

const counter = new Counter();

パターン3: 両方必要な場合

イベントターゲットと外側のスコープの両方が必要な場合は、イベントオブジェクトのcurrentTargetプロパティを使用します。

class ButtonManager {
  constructor() {
    this.clickCount = 0;
    
    document.querySelectorAll('.button').forEach(button => {
      button.addEventListener('click', (event) => {
        this.clickCount++; // 外側のthis(ButtonManagerインスタンス)
        
        const clickedButton = event.currentTarget; // イベントターゲット
        clickedButton.textContent = `クリック数: ${this.clickCount}`;
      });
    });
  }
}

以下の図で、各パターンの使い分けを整理してみましょう。

まとめ

addEventListenerにおけるthisの挙動は、使用する関数の種類によって変わります。

  • 通常の関数: thisはイベントターゲット要素を参照
  • アロー関数: thisは外側のスコープのthisを参照

どちらを使うかは、実装したい処理によって使い分けましょう。要素自身を操作したい場合は通常の関数、外側のスコープにアクセスしたい場合はアロー関数が適しています。

この仕組みを理解しておくことで、イベント処理の実装がよりスムーズになりますね。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?