クリックイベントとthisとラムダ式

前回の記事でJavaScriptは発火場所によってthisのコンテキストが違うことがわかりました。

今回は、それを踏まえて自分がハマった箇所をご紹介します。

    var price = 100

    const testbtn = document.getElementById("test")
    
    const func = function(){
        console.log(this)
        console.log(this.price)
        console.log("clicked!")
    }

    testbtn.addEventListener('click',func)

グローバルオブジェクトにpriceを紐づけるため、varを使っています。
そしてhtml要素の中にはbuttonを用意します

<button id="test">ClickMe!</button>

このボタンを押下した時にfuncメソッドが呼ばれるのですが、グローバルに登録してあるpriceにthisを使ってアクセスできないという自体が発生します。

btn.html:12 <button id=​"test">​ClickMe!​</button>​
btn.html:13 undefined
btn.html:14 100
btn.html:15 clicked!

thisのコンテキストがbuttonなのでbuttonにはpriceがないのでundefinedとなります。

次は2つのボタンを用意します。
同じくコールバック関数を定義ます。一つは無名関数で、もう一つはラムダで定義します。

    var price = 100

    const testbtn = document.getElementById("test")
    const hogebtn = document.getElementById("hoge")
    const masterbtn = document.getElementById("master")
    
    const func = function(){
        console.log(this)
        console.log(this.price)
        console.log("clicked!")
    }

    testbtn.addEventListener('click',func)


    hogebtn.addEventListener('click',function(){
        console.log(this)
        //<button id="hoge">ClickMe!</button>
        console.log(this.price)
        //undefined
    })

    masterbtn.addEventListener('click',()=> {
        console.log(this)
        //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
        console.log(this.price)
        //100
    })
    

結果をコメントに書いたのですが、ラムダと無名関数ではthisの値が変わっていて、ラムダで定義したほうではthis.priceにアクセスすることができます。

なぜこのようなことが起きるのか?jsでは関数が呼ばれた時に、呼び出し元のオブジェクトがthisになるとです。

ボタンを押下した時の呼び出し元はボタンであるため、this.priceとしてもボタンにpriceがないためアクセスできませんでした。。

しかしラムダ式を使うと宣言時のthisを束縛します。表現がアレですが公式的な表現です笑い

ラムダ式を定義したときのthisとなるのでボタンではなくwindowということになるのですね。

bind関数などを使ってthisを明示的に操作していましたが、ES2015からはラムダ式でthisを束縛して操作できます。

コメント

タイトルとURLをコピーしました