はじめに
本記事では JavaScript における this について解説します。
とてもややこしく自分でもなかなか頭に定着しないので忘備録として記載します。
なお、多くの場合 this はグローバルオブジェクトを指すので、そもそもグローバルオブジェクトとは何かというのは予備知識として必要になります。
JavaScript基礎知識~グローバルオブジェクトについて~ - まるノート
なお、本記事ではアロー関数における this や、bindメソッドなどは扱わず、基本の部分だけに焦点をあてた内容です。
this キーワード
this が何を指すか、はコードの文脈によって変化します。
まず押さえておくべきは以下の2つです。
・オブジェクトのメソッドにおける this
・関数における this
さらに理解を深めるため以下の少しややこしいパターンについても検証してみます。
- オブジェクトのメソッドを関数として実行した場合の this
- 関数をオブジェクトのメソッドとして呼び出した場合の this
- オブジェクトのメソッドをコールバック関数として渡した場合の this
オブジェクトのメソッドにおける this
まずは一つ目です、オブジェクトのメソッドとして呼び出された関数内での this は、
その呼び出し元のオブジェクトを指します。
const obj = { name: 'Taro', method: function() { console.log( 'this : ', this ); console.log( 'this.name : ', this.name ); } } obj.method();
結果
この場合の this は呼び出し元である obj を指しているのがわかりました。
関数における this
次に単なる関数を実行した場合の this を見てみます。ものすごくシンプルな例です。
function func() { console.log( 'this : ', this ); } func();
結果
関数を実行した場合、関数内の this はグローバルオブジェクトである window を指します。
※グローバルオブジェクト = window はブラウザで実行したケースです。
ややこしいパターン
ひとまず上で紹介したケースは超基本です。
以下の場合だと this は何を指すようになるか、理解を深めるために試してみます。
オブジェクトのメソッドを関数として実行した場合
- オブジェクトのメソッドを定義する
- 定義したメソッドを変数に代入する。
- その変数を関数として実行した場合の this
const obj = { name: 'Taro', method: function() { console.log('this : ', this); console.log('this.name : ' + this.name); } } const func = obj.method; //オブジェクトのメソッドを代入 func();
結果
実行したのはオブジェクトのメソッドですが、一度変数に代入して関数呼び出し演算子( )で実行した場合、 関数内の this はグローバルオブジェクトである window を指します。
※windowオブジェクトにはどうやら name というプロパティが標準的に存在しているようです。 そのため this.name の部分は undifined にはなりませんでした。
関数をオブジェクトのメソッドとして呼び出した場合
先ほどの例とペアで覚えると良いかもしれません。
- 通常の関数を定義する
- 定義した関数をオブジェクトのメソッドに代入する
- オブジェクトのメソッドを実行した場合の this
function func() { console.log('this : ', this); console.log('this.name : ' + this.name); } const obj = { name: 'Taro', method: func // obj のメソッドに代入 } obj.method();
結果
結果、通常どおり定義した関数は、オブジェクトのメソッドとして呼び出した場合には、
this は呼び出し元のオブジェクトを指すことがわかりました。
オブジェクトのメソッドをコールバック関数として渡した場合の this
最後はコールバック関数における this です。
コールバック関数では、呼び出す側の関数と呼び出される側の関数の二つを考える必要がありました。
コールバック関数としてオブジェクトのメソッドを、呼び出す側の関数の引数に与えたらどうなるかを試してみます。
const obj = { name: 'Taro', hello: function() { // コールバック関数として与えるメソッド console.log('this : ',this); console.log('this.name : ', this.name); } } function func(callback) { callback(); } func(obj.hello);
結果
一番初めに記載した通り、オブジェクトのメソッドを実行した場合そのメソッド内の this は 呼び出し元のオブジェクトを指すはずでした。
しかしコールバック関数として与えた場合、this が指すのは window オブジェクト という結果になります。
コールバック関数としてオブジェクトのメソッドを渡した場合、関数への参照(関数のアドレス)が渡されるだけで、obj の情報が渡されるわけではないようです。 (詳細は割愛します、あまり詳しく検証していません。。) そのため、ただの関数呼び出しとなり、this はグローバルオブジェクトを参照します。
以上、関数の種類により this が指すものがどのように変化するかの解説でした。
本記事では触れられなかった、アロー関数における this や、this を束縛するための bind メソッドといった内容は近々別の記事にしたいと思います。