JavaScriptのaddEventListenerで関数に引数をわたす方法(bind)
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も不要になります。
今回は一つの引数のみですが、さらに複数の引数を渡す必要がある場合は、配列やオブジェクトを入れて渡します。