コールバック関数でのthisの扱いに注意!
- 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/




