プログラミング入門ナビ編集部はじめにJavaScriptの「this」は他の言語と比較し挙動に少々癖があります。呼び出し方によってどの値を指すかが変わるためです。思ったような値が得られない時は、thisの呼び出し方に問題があるかもしれません。この記事では呼び出し方の違いによるthisの挙動を説明します。thisの呼び出し方:基礎編まずはよく使われるオーソドックスな呼び出し方を見ていきましょう。//3func();//4上記1234では何が表示されるでしょうか。答えは下記のようになります。//4正解できましたか?1234はいずれもthis.valueの呼び出しをしていますが、この通り表示される値が違います。このようになるのか、順を追って説明していきます。グローバルコンテキストでの呼び出し1ではthisをグローバルコンテキスト(関数やオブジェクトの外側)で呼び出しています。この場合、thisにはグローバルオブジェクトが入ります。グローバルオブジェクトはJavaScriptが実行される環境により変わるのですが、ブラウザの場合はWindowオブジェクトとなります。下記のようにconsole.logでthisを表示させればグローバルオブジェクトが何なのか確認できます。1;としたことで、このグローバルオブジェクトにvalueという値が定義され1が代入されていたため1が表示されました。このように、グローバルコンテキストでthisを呼び出すと、グローバルオブジェクトが入ります。オブジェクトのメソッド呼び出し2は「objオブジェクトのfunc」をメソッド呼び出しています。このように「〇〇.func();」といった具合で関数呼び出しの前に「〇〇.」がつく場合、関数「func」のスコープ内でのthisが指すのは前置きの〇〇が示すオブジェクトです。この例ではobjのfunc関数スコープ内でthisが呼び出されているので、このthisが指すのは自分自身であるobjオブジェクトですね。objは自身のvalueを持つため、結果的にthis.valueはこれを呼び出して2が入ります。3は同じくobjの中で定義されたfuncを実行しているのですが、testにobj.funcを代入したあとでtest();と前置きなしで呼び出されていますね。このように、グローバルコンテキストで前置きなしに関数だけが呼び出されている場合の関数内thisは、次項の「関数呼び出し」のケースにあたりグローバルオブジェクトを指すため1が表示されます。関数呼び出し4はグローバルコンテキストで定義された関数funcを呼び出しています。メソッド呼び出しではないので、「〇〇.」のような前置きはありません。この場合の関数内thisもグローバルオブジェクトを指します。グローバルオブジェクト(ブラウザで実行の場合はWindowオブジェクト)のvalueは一行目で定義されている通り1なので、1が表示されるわけです。基礎編で見たように、thisの挙動は呼び出し方によって変わります。thisに何を入れたいかを明示的に指定するためのいくつかの方法を紹介します。アロー関数呼び出しES6からはアロー関数が使用できるようになりました。関数としての基本的な挙動は通常の関数(function)と変わらないのですが、関数スコープ内のthisについては挙動が異なります。アロー関数の中で呼び出されたthisは、関数の呼び出され方に関わらず、その関数が最初に定義された時点で指していた対象を指し続けるのが特徴です。func2}obj1.func1();//1が表示されるobj2.func2();//5が表示されるfunc1は従来の関数、func2はアロー関数です。この時点では両方ともグローバルコンテキストで定義されているため、thisはグローバルオブジェクトを指します。その後に2種類のオブジェクト:obj1とobj2が定義され、それぞれfunc1とfunc2を保有していますね。obj1のメソッド呼び出しでは、基礎編で触れたようにthisはobj1を指すので、obj1が持つvalueの値である1が表示されます。これに対し、obj2のメソッド呼び出しではfunc2がアロー関数なので、thisが指すのはobj2でなく定義された時点で指していたグローバルオブジェクトのままです。結果として、ojbのvalue(値は2)でなく、グローバルのvalue(値は5)が表示されます。このように、アロー関数を使うと呼び出され方によらずthisが指す対象を定義当初のまま固定できるのです。関数のコンストラクタ呼び出し関数をグローバルコンテキストで前置き無しに呼び出すとその関数内でのthisはグローバルオブジェクトを指すのでした。関数をコンストラクタ呼び出しすると、関数自体がインスタンスとなりthisは自身を指すようになります。Object]が表示される1行目の関数を2行目で呼び出した場合はthisはグローバルオブジェクトであるWindowオブジェクトになりますが、3行目のようにコンストラクタ呼び出しをするとObjectオブジェクトとなっていることが分かりますね。実際に通常の関数呼び出しとコンストラクタ呼び出しの挙動を比較してみましょう。MyObject(3);//3が表示されるconsole.log(this.value);//5が表示されるmyObj.show();//3が表示される6行目が通常の関数呼び出し、7行目がコンストラクタ呼び出しです。関数MyObjectではthis.valueに引数の値を代入しますが、通常呼び出しではグローバルオブジェクトのvalueに、コンストラクタ呼び出しでは自身(MyObjectのインスタンス)のvalueに値を入れています。そのため6行目・8行目ではグローバルvalueが呼ばれるので5が、7行目・9行目ではMyObjectインスタンスのvalueが呼ばれるので3が表示されるわけです。apply・call関数を使った呼び出し関数呼び出しにおいてthisに何を入れるか明示的に指定できるのがapply関数とcall関数です。使い方を見てみましょう。}func();//0が表示されるfunc.call(obj1);//1が表示されるfunc.apply(obj2);//2が表示される4行目の関数funcのthisはグローバルオブジェクトを指すので、6行目のように呼び出すとグローバルのvalueである0が表示されますね。7行目・8行目のようにcallやapply関数を使って呼び出すと引数に指定したオブジェクトをthisとして指定することができるので、それぞれobj1・obj2のvalueである1と2を表示します。call・applyでは関数に渡す引数を設定することもでき、その方法によりこれらを使い分けます。詳しくはドキュメント(MDN)を参照してください。まとめJavaScriptでのthisについて、呼び出し方による挙動の違いを説明しました。最初は理解しにくいので、実際にコードを書いて試していくのがおすすめです。・About・プライバシーポリシ。