thisについて|webpack

Javascriptのアロー関数について勉強していて、thisの取り扱いがよくわからなかったのでメモ。

thisの参照先

アロー関数はthisの束縛という言葉で表現される、関数を定義した時点でのthisの値を保持するという性質を持つ。

例えば以下のような処理を<script>に書いた場合

this.param = "global param"

//通常の関数
function normalFunc() {
    console.log(this.param)
}

//アロー関数
let arrowFunc = () => {
    console.log(this.param)
}

// オブジェクトのメソッドとして定義
let object = {
    param: "object param",
    func: normalFunc
}

let object2 = {
    param: "object2 param",
    func: arrowFunc
}

//実行
normalFunc()
arrowFunc()
object.func()
object2.func()

実行結果は以下のようになる。

global param
global param
object param
global param

通常の関数、アロー関数ともに、直に関数を実行するとglobal paramが返る。

次にメソッドとして定義して実行すると、通常関数ではobject paramが返され、アロー関数は変わらずglobal paramを返す。

これは通常関数がオブジェクト内で実行された場合、関数を内包するオブジェクトをthisとして実行されるため、オブジェクトのパラメータであるparamの変数の値を返しているからである。

一方アロー関数は現在の位置によりthisを入れ替えることをせず、関数を定義した時点でのthisを保持しているため、global paramを返す。

トランスパイル時のアロー関数のthis

ざっくり言うとbabelではthisがwindowオブジェクトを指す場合はundefindとなる仕様だそう。

上記のテストコードは当初webpackで書いていたが、この仕様に沿う結果なのか、globalのthisがすべてundefindとなるため、globalに定義したアロー関数内に書かれたthisもすべてundefindになり、webpack環境下では上記のような単純なコードさえまともに動かなかったため、scriptに直書きする形にしてみたら普通に動いた。

それを踏まえ、アロー関数を書いてthisを扱う際に通常関数と異なる動きをするサンプルを書きたかったがうまく書けず…現状の自分のスキルでは理解が足りないようで、どう書いても通常関数とアロー関数が同じ値となってしまった…

クソコードだけど、とりあえず記録として残しておく。

  let myFunc = {
    param: "func param",
    //通常関数
    normalFunc: function () {
      console.log(this.param)
    },
    //アロー関数
    arrowFunc: function () {
      let arrow = () => {
        console.log(this.param)
      }
      arrow()
    },
  }

  let myObj = {
    param: "obj param",
    func1: function() {
      myFunc.normalFunc()
    },
    func2: function() {
      myFunc.arrowFunc()
    }
  }
  //実行
  myObj.func1()
  myObj.func2()

実行結果は以下のようになる。

normal:func param
arrow:func param

期待したのは以下のような結果。

normal:obj param
arrow:func param

通常関数に関しては呼び出された位置によりthisが書き換わるんちゃうんか…わからん…

でもアロー関数についてや、thisの取り扱いについて多少なり経験となったのでよしとする。

もし上記の疑問が解消したらさかのぼってこの記事を修正する。