ゆるふわ技術日誌

エンジニア見習いの悪戦苦闘日記

JavaScriptのインスタンスメソッドを変数に代入してはいけない

JSerにとっては当たり前の事なのかもしれないが、うっかりハマってしまったので備忘録として書いておく。


こんな感じのコードがあったして…

class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

const user = new User('mirin');

UserクラスのインスタンスであるuserのgetNameメソッドを呼び出します。

user.getName() // -> mirin

これは間違いなく、インスタンスかする時にコンストラクタで指定した名前が返ってきます。

しかし、以下のような感じで呼び出すと…

const gn = user.getName
gn() // -> Uncaught TypeError: Cannot read property 'name' of undefined

となる。

なぜか。

(ちょっとこの辺は正確さに欠ける表現があるかもしれないので、ご承知おきください)

JavaScriptthisは、呼び出したオブジェクトが入ります。(アロー関数を使った場合の挙動は別になります。要注意)

user.getName()の場合は、userがthisになるため、名前を取り出す事ができますが、メソッド自体を変数に代入して呼び出してしまうと、thisはundefinedとなってしまうため↑に示したエラーが起こります。

ちなみに

実際に僕がやらかしたのは、条件によって呼び出すメソッドを変える必要があるという、割と複雑なロジックを書いていた場面でした。

結局、それくらい複雑なことをやるなら関数分けた方がいいよね、となってやめたのですが、もしインスタンスメソッドを変数に代入したい場合は、

const gn = user.getName.bind(user)
gn() // -> mirin

という感じで、bindを使ってthisを束縛してやればOKです。もしくはメソッドの定義をアロー関数を使う、でもOKです。