3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

オブジェクト指向プログラミングなremoveEventListenerの書き方

Last updated at Posted at 2020-03-30

記事を書いたのにremoveEventListenerでまた躓いた。:confounded:

今回はオブジェクト指向プログラミング版。

失敗例

class X {
  click(e) {
    // thisがオブジェクトXを指すようにしたい
    console.log('click', this, e.currentTarget);
  }
  add() {
    document.addEventListener('click', (e) => this.click(e));
  }
  remove() {
    document.removeEventListener('click', (e) => this.click(e));
  }
}
var x = new X();
x.add();
x.remove();

(()=>{}) === (()=>{})(function(){}) === (function(){})がfalseを返すのでremoveEventListenerに無名関数を使用できない。

addEventListenerで指定した関数と同じ関数をremoveEventListenerで指定できていないのでイベントリスナーを削除できない。

イベントリスナー関数にthis.clickを指定するとremoveEventListenerで削除できるが、thisがdocumentを指し、e.currentTargetもdocumentを指すので重複してしまう。

オブジェクト指向プログラミングでイベントリスナー関数は書けない?

ここで小一時間悩んだ。:thinking:

成功例1 (bind)

class X {
  constructor() {
    this.event_listeners = {};
  }
  click(e) {
    // thisがオブジェクトXを指すようにしたい
    console.log('click', this, e.currentTarget);
  }
  add() {
    this.event_listeners.click = this.click.bind(this);
    document.addEventListener('click', this.event_listeners.click);
  }
  remove() {
    document.removeEventListener('click', this.event_listeners.click);
  }
}
var x = new X();
x.add();
x.remove();

関数にthisをbind1して、その関数を保存して書けばいいと思う。:blush:

成功例2 (handleEvent)

あらゆるイベントを捕捉する handleEvent() という特別な関数が存在した。2

handleEventを使うとどうなるか。

class X {
  click(e) {
    // thisがオブジェクトXを指すようにしたい
    console.log('click', this, e.currentTarget);
  }
  add() {
    document.addEventListener('click', this);
  }
  remove() {
    document.removeEventListener('click', this);
  }
  handleEvent(e) {
    if (e.type === 'click' && e.currentTarget === document) {
      this.click(e);
    }
  }
}
var x = new X();
x.add();
x.remove();

この方法でもイベントリスナーを削除できる :smile:

オブジェクトxのすべてのイベントが1つの関数handleEventに集約されるので、オブジェクトのイベントが多くなったときデバッグしやすくなるかもしれない。

  1. this.event_listeners.click = (e) => this.click(e)と書いてもいい。addEventListenerがthisを書き変えるのでthis.event_listeners.click = function (e) { this.click(e) }とは書けない。

  2. EventTarget.addEventListener() - Web API | MDN

3
4
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
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?