JavaScriptのaddEventListenerで関数に引数をわたす方法(bind)

2021年2月28日JavaScript

JavaScriptのaddEventListenerで関数に引数をわたす方法を紹介します。 bind()メソッドを使った方法です。 なぜ失敗するのかを把握することも大事なので、失敗例も合わせて記載します。 addEventListenerの使い方は、次の記事を参考にしてみてください。 bind()メソッドの使い方は、次の記事を参考にしてみてください。

addEventListenerで関数に引数を渡せていない失敗例

順を追って説明するために、まずは失敗例から紹介します。


//関数
const handleHover = function(e, opacity) {

    if(e.target.classList.contains('nav__link')) {
      const link = e.target; 

      const siblings = link.closest('.nav').querySelectorAll('.nav__link');
      const logo = link.closest('.nav').querySelector('img');
  
      siblings.forEach(el => {
        if(el !== link) el.style.opacity = opacity;
      });
      logo.style.opacity = opacity;
    }

//動かない。関数は渡せているものの、引数を渡せていません。なので動きません。
   nav.addEventListener('mouseover', handleHover);
}
関数にe,opacityという引数を渡したいとします。 addEventListenerの第二引数に、上のように関数を渡します。 これは、動きません。 関数は渡せているものの、引数を渡せていません。なので動きません。

addEventListenerで関数ではなく値を渡してしまっている失敗例



//関数
const handleHover = function(e, opacity) {

    if(e.target.classList.contains('nav__link')) {
      const link = e.target; 

      const siblings = link.closest('.nav').querySelectorAll('.nav__link');
      const logo = link.closest('.nav').querySelector('img');
  
      siblings.forEach(el => {
        if(el !== link) el.style.opacity = opacity;
      });
      logo.style.opacity = opacity;
    }

//動かない。関数ではなく実行された値を渡してしまっている。
   nav.addEventListener('mouseover', handleHover(e, 0.5));
}
上の関数handleHover部分は同じです。 addEventListenerの第二引数には、関数そのもの(=handleHover)」を指定しなければいけません。 handleHover()をわたすと、「その関数の実行結果の値」を渡していることになり、関数を渡していません。 つまり、handleHover()やhandleHover(opacity)としても値であって、関数ではないので動きません。

addEventListenerで関数を渡せている成功例(コードが冗長になる)


//関数
const handleHover = function(e, opacity) {

    if(e.target.classList.contains('nav__link')) {

      console.log(this, e.currentTarget);//thisはundefined, e.currentTargetはnavを指定しているので、navタグになります。
      const link = e.target;
  
      const siblings = link.closest('.nav').querySelectorAll('.nav__link');
      const logo = link.closest('.nav').querySelector('img');
  
      siblings.forEach(el => {
        if(el !== link) el.style.opacity = opacity;
      });
      logo.style.opacity = opacity;
    }
}

//動く例1 
nav.addEventListener('mouseover', function(e) {
  handleHover(e, 0.5);
});
nav.addEventListener('mouseout', function(e) {
  handleHover(e, 1);
});
これはコールバック関数を渡しているので動きます。 ただし、複数あるとコードが冗長になるのと、解除(アンバインド)する事が出来ません。

addEventListenerのthis

const button = document.querySelector("button");

const red = function () {
  // button.style.color = "green"; //buttonではなくthisでOK
  this.style.color = "green";
};

button.addEventListener("click", red);
こちらの例では、buttonにaddEventListener()が登録されているため、buttonがthisの参照先となります。 そのため、コールバック関数でthisを使用すると、buttonを指します。

addEventListenerでbindを使って引数を渡す成功例

上の方法は、2つも同じコードを書いています。 このような場合、bindでthisを決めるといいです。


//関数
const handleHover = function(e) {//opacityが不要になります。

    if(e.target.classList.contains('nav__link')) {
      console.log(this);//0.5 / 1が表示される

      const link = e.target;
  
       const siblings = link.closest('.nav').querySelectorAll('.nav__link');
      const logo = link.closest('.nav').querySelector('img');
  
      siblings.forEach(el => {
        if(el !== link) el.style.opacity = this; //ここはopacityではなく、thisでOKになります。
      });
      logo.style.opacity = this; //ここはopacityではなく、thisでOKになります。
    }
}
//動く例2
nav.addEventListener('mouseover', handleHover.bind(0.5));
nav.addEventListener('mouseout', handleHover.bind(1));//bindは新しい関数を返します。
bind()は新しい関数を返します。そしての関数は0.5という値が設定されています。 関数内でコンソールにthisを表示すると0.5が渡せていることがわかります。 thisは通常currentTargetとイコール。しかし、いまのcurrentTargetはnavタグになるため、それをbind()で手動で指定します。 つまり、opacityはthisで表せるので、opacityも不要になります。 今回は一つの引数のみですが、さらに複数の引数を渡す必要がある場合は、配列やオブジェクトを入れて渡します。

JavaScript

Posted by devsakaso