JavaScriptのthisってなんぞや


JavaScriptについて調べていけばいくほど、「this」が何を指しているのかわからなくなってきました。自分なりに検証してみた結果を書いて行きたいと思います。

ChromeSafariのWeb Inspectorを開いて、コンソールに直接コードをペーストしてEnterで実行するのが一番簡単にコードを確認できます。

試しに関数も何も作らず、単に「this」を表示してみます。
console.log(this); //windowオブジェクト
この場合「this」はwindowオブジェクトを指すようです。つまり、グローバルオブジェクトですね。

次に関数内でどのような扱いになるのでしょうか。
function thisTest(){
console.log(this);
}

thisTest();// windowオブジェクト
newも何も使わずに単に関数内に書いた場合も「this」はwindowオブジェクトを指すようです。

では、thisの属性や宣言なしの変数はどうなるのでしょうか。
function thisTest(){
this.a = "hoge";
b = "hage";
console.log(this);
}
thisTest();// windowオブジェクト
コンソールに表示されるwindowオブジェクトの中身を見てください。
windowオブジェクトの中に膨大なプロパティがあると思いますが、そのなかに「a: "hoge"」や「b: "hage"」などがあることから、varを使わない変数はwindowオブジェクトのプロパティとなることがわかります。
また、その中に「thisText()」もあり、この関数もwindowオブジェクトのプロパティとみなされていることがわかります。

次にnewを使った場合はどうなるのでしょうか。
function ThisTest(){
this.a = "hoge";
b = "hage";
console.log(this);
}
var thisTest = new ThisTest(); // ThisTestオブジェクト
こちらは「ThisTest」オブジェクトが表示されています。
newをするとインスタンスを作成し、thisはそのインスタンスを指していることがわかります。ThisTestの中には「a: "hoge"」とあり、「b」は表示されていません。この場合の「b」はThisTestのプロパティではなく、windowsオブジェクトのプロパティになります。

オライリーの「JavaScriptパターン」には下記のように書かれています。
var Person = function (name) {
    this.name = name;
    this.say = function () {
        return "I am " + this.name;
    };
};
このコンストラクタ関数を new を使って呼び出すとき、関数内部での動作は以下のようになりま す。

・空のオブジェクトが作成され、変数 this で参照されます。this はこの関数のプロトタイプを 継承しています。
・this が参照するオブジェクトにプロパティとメソッドが追加されます。
・ this が参照する新しく作られたオブジェクトは、関数の最後で(明示的に別のオブジェクトを 返していなければ)暗黙に返されます。

Stoyan Stefanov著、豊福 剛訳(2011) 『JavaScriptパターン』 株式会社オライリー・ジャパン 244pp.
つまり、

  • 単に「this」を使った場合はグローバルオブジェクト(≒windowオブジェクト)を指す。
  • 関数内の「this」はnewで作成した場合、インスタンスのことを指す。


ということでしょうか。少しスッキリしました。