0
0

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.

bind()を使ってイベントハンドラに引数を渡す

Posted at

どうにかして、イベントハンドラにスコープ外の変数の値などを渡したいときがある。
色々方法があると思うが、最近bind()を使ったらいいんじゃないかと思ったので紹介する。
他で紹介されているのを見ない気がするので、もしかしたら欠点があるのかもしれない。

bind()を使う

bind() の引数には、thisの値以外にも値が渡せるので、それを利用する。
Function.prototype.bind() - JavaScript | MDN

HTML

<button id="btn">Click!</button>

JavaScript

{
    let value = "Hello!"; //スコープ外の変数
    let btn = document.querySelector("#btn2");
    let bindedHandler = handleClick.bind(btn, value); // bindにvalueの値を渡す
    btn.addEventListener("click", bindedHandler);
}

//スコープ外にあるイベントハンドラ
function handleClick(val, event) {
    console.log(typeof value); // undefined
    console.log(val);          // Hello!
    event.preventDefault();
}

bindの2つ目以降に渡した引数は、新しく生成された関数が呼び出された際に、既存の引数の先頭に渡される。
通常、イベントハンドラにはeventオブジェクトが引数として渡されるので、bindに渡した引数はその前に来ることになる。
イベントハンドラの定義に引数が増えてしまうし、イベントオブジェクトが2番目以降に行ってしまうのでので、もう少し工夫したほうがいいかもしれない。

工夫した例

可変長引数をつかって引数の長さに応じて分岐させるようにしてみた。
冗長になったが、これならイベントハンドラを使い回すようなこともできる。

{
    let value = "Hello!"; //スコープ外の変数
    let btn = document.querySelector("#btn");
    let bindedHandler = handleClick.bind(btn, value);
    btn.addEventListener("click", bindedHandler);
}

//スコープ外にあるイベントハンドラ
function handleClick(...args){
    let event,
        len = args.length;
    if (args.length > 1) {
        event = args[len - 1];
        args.forEach((e, i) => {
            if (i + 1 !== len) {
                console.log(e); //Hello!
            }
        });
    }
    else {
        event = args[0];
    }
    event.preventDefault();
}

オーソドックスな方法

一応、bindを使わない、よくある方法も紹介する。

イベントハンドラを無名関数にして、イベントハンドラ内から別の関数を呼ぶ

{
    let value = "Hello!"; //スコープ外の変数
    let btn = document.querySelector("#btn");
    btn.addEventListener("click", function(event) {
        event.preventDefault();
        anotherHandleClick(value);
    });
}

anotherHandleClick(val) {
    console.log(val); // Hello!
}

イベントハンドラを返す関数を呼ぶ

{
    let value = "Hello!"; //スコープ外の変数
    let btn = document.querySelector("#btn");
    btn.addEventListener("click", anotherHandleClick(value));
}

anotherHandleClick(val) {
    //イベントハンドラを返す
    return function(event){
        event.preventDefault();
        console.log(val); // Hello!
    };
}

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?