Javascript

【JavaScript】イベントのthisとbind

こんにちは、ともです。

JavaScriptのthisの参照先というのは『文脈による』というのはご存知だと思います。もし知らなければ下記の記事を読んでみて下さい。

今回はイベントリスナー・イベントハンドラー内でのthisの参照先とbindメソッドについて理解をまとめます。

イベントリスナー/ハンドラ配下のthis

JavaScriptは文脈によって参照先が変化する不思議なものです。

イベントリスナー・ハンドラ配下のthisは、イベントの発生元(要素)を表します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button id="btn">ぼたん</button>
</body>
<script>
    document.getElementById('btn').addEventListener('click', function() {
        console.log(this);
        //<button id="btn">ぼたん</button>
    });
</script>
</html>

上記のようにイベントリスナ内のthisの参照先は、イベント発生元の要素(ボタン要素)を参照していることが分かります。

注意するべき例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button id="btn">ぼたん</button>
</body>
<script>
    document.addEventListener('DOMContentLoaded', function () {
        var data = {
            name: 'tomo',
            show(){
                console.log('my name is ' + this.name)// my name is 
            }
        }
        document.getElementById('btn').addEventListener('click', data.show, false);
    }, false);
</script>
</html>

ボタンがクリックされた場合にdata.showが実行されるイベントを登録しました。

しかし、結果はmy name isとなりmy name is tomoとはなりません。

これはイベントリスナ内のthisはイベント発生元の要素を参照しているためです。

本来参照してほしい場所はdataオブジェクトにも関わらず、thisは<button id="btn">ぼたん</button>を参照します。

これを意図した挙動になるには、どのようにすべきでしょうか?

イベントリスナのthisの参照先指定方法

前述のような、イベントリスナ内のthisがイベント発生元の要素を参照することにより起こる不都合を回避するにはどうすれば良いでしょうか?

  1. Functionオブジェクトのbindメソッド
  2. EventListenrオブジェクトを利用

Functionオブジェクトのbindメソッド

  • func.bind(that [, arg1 [arg2 [,…]]])

func:関数オブジェクト

arg1, arg2..:関数の引数

that:関数内でのthisの参照先

関数オブジェクトにはbindメソッドが登録されています。

これにより、関数内のthisキーワードを指定することができます。

先ほどの例ですと

document.getElementById('btn').addEventListener('click', data.show.bind(data), false);

こうすることで、thisの参照先をdataに指定することができます。

EventListenerオブジェクトを利用

EventListerオブジェクトとは

EventListenerオブジェクトとはhandleEventメソッドを持っているオブジェクトのことを言います。

var data = {
            name: 'tomo',
            show(){
                console.log('my name is ' + this.name)// my name is 
            }
 }

前述のこのオブジェクトはhandleEventと言うメソッドを持っていないため、次のようにhandleEventを登録することでEventListerオブジェクトとなります。

var data = {
            name: 'tomo',
            handleEvent: function () {
                console.log('my name is ' + this.name)
            }
 }

これによりdataオブジェクトはEventListerオブジェクトとなりました。

EventListerオブジェクトを利用したthisの参照先指定

EventListerオブジェクトをイベントリスナの第二引数に指定すると、handleEvent内のthisの参照先はEventListerオブジェクトに固定されます。

document.addEventListener('DOMContentLoaded', function () {
        var data = {
            name: 'tomo',
            handleEvent: function () {
                console.log('my name is ' + this.name)
            }
        }
        document.getElementById('btn').addEventListener('click', data, false);
    }, false);

これによりthis.namedata.nameを参照するようになります。

まとめ

イベントリスナ/ハンドラ内でのthisの参照先が意図した挙動になるように

  • bind
  • EventListerオブジェクト

を紹介しました。

そのほかにもアロー関数を利用するとthisの参照先を束縛することが可能です。