- JavaScript
- 2022-05-02
JavaScriptのクラスやオブジェクトリテラルでコーディングしていて、他の言語と同じ感覚でthis
キーワードを使用しているとバグが発生する可能性があります。
他の言語だとthis
というとクラスやオブジェクト自身を参照するのですが、JavaScriptだと少し違って、通常は同じようにクラスやオブジェクト自身を参照してくれるのですが、コールバック関数で呼び出された場合はwindow
を参照するのです。
これを知らないと意図しない動作でバグとなり、エラーが発生しますのでご注意ください。
実際にサンプルコードを踏まえて説明します。
まずはコールバック関数を実行するメソッドを含んだオブジェクトを作成します。
const exam1 = { a: function(callback) { callback(); } }
次に、コールバック関数を引数に与えて、先ほどのオブジェクトのメソッドを実行するためのオブジェクトを作成します。
const exam2 = { b: function() { console.log("function b!"); }, c: function() { this.b(); }, d: function() { exam1.a(exam2.c); } }
実行する順番としては次の通りです。
exam2.d
を実行exam1.a
にコールバック関数の引数としてexam2.c
を渡して実行exam1.a
によりexam2.c
が実行されるexam2.c
によりthis.b
が実行される
しかしながらthis.b
が実行された時点で
Uncaught TypeError: this.b is not a function
というエラーが発生します。 ※this.b
=exam2.b
exam2.b
という関数は宣言してあるのになぜ?と思いますよね。
ここでエラーが発生する原因はexam1.a
により実行されるexam2.c
の中でthis
キーワードが使われていることです。
コールバックにより実行される関数の中でのthis
キーワードがwindow
オブジェクトを参照しているからで、window
オブジェクトにはbメソッドがないのでエラーになるのです。
ここが他の言語とは異なっています。
対応策として、アロー関数をコールバック関数として渡すことでエラーを回避できます。
exam2.d
を以下のように書き換えます。
d: function() { exam1.a(() => { exam2.c(); }); }
こうすることで、this
キーワードがexam2
を参照し正常に実行できるようになります。
参考URL:
https://pisuke-code.com/javascript-class-this-in-callback/