さぁ!検索しよう!

JavaScriptのthisは呼び出し元によって何を指すのかが異なります。

インスタンスによって呼び出される場合

クラスに定義されているメンバ変数や、クラスのプロトタイプに定義されている関数(メソッド)内のthisは、クラスやそのプロトタイプを指さず、生成されたインスタンスを指します。

function Neko(n){
	this.name=n;
}
Neko.prototype.appear=function(){
	console.log(this.name+'が現れた。');
}
var tama = new Neko('タマ');
tama.appear();//appear()内のthisはインスタンスtamaを指す

続いて、例えば同じクラスから複数のインスタンスを生成した場合のthisは、それぞれ呼び出されたインスタンスのみを指します。

function Neko(n){
	this.name=n;
}
Neko.prototype.appear=function(){
	console.log(this.name+'が現れた。');
}
var tama = new Neko('タマ');
tama.appear();//appear()内のthisはインスタンスtamaを指す
var momo = new Neko('モモ');
momo.appear();appear()内のthisはインスタンスtamaを指す

つまり、元のクラスは同じであってもインスタンス毎にthisの対象は異なります。

オブジェクト内に関数を定義した場合の関数内のthis

関数内のthisが指すオブジェクトも場合によって異なります。

オブジェクトhoge内にプロパティhoge:"hoge"を定義した場合は、オブジェクトに属するプロパティとなります。しかし同様に、関数を定義した場合は、オブジェクトに属する関数とはならず、あくまでhoge内のmethodに関数のアドレス情報を代入しただけの状態となります。

要は、関数はオブジェクト内で定義されたものであっても、独立したオブジェクトなのです。

なので下記のようなコードは、hoge.methodfoo.methodに代入したことで、hoge.method内のthisはそれまで指していたhogeではなくfooを指します。

var hoge = {
  value: 1,
  method: function() {//関数のアドレス情報をmethodに代入
    console.log(this.value);
  }
}
hoge.method();//1
var foo = {
	value:2,
	hogemethod:hoge.method//関数のアドレス情報をmethodに代入
}
foo.hogemethod();//2

hogemethod:hoge.methodは書かずにfooからhogemethodを直接呼び出し、foo.method()としたいところですが、これだとfoo内にmethodが定義されていないというエラーが起こります。

オブジェクト内に定義されていない関数内のthisが指すもの

下記のコードでは、関数のみが定義されており、その関数内にthisが存在します。

この関数を実行すると、コンソールに私の名前はundefinedです。と出力されます。

function hoge(){
	var n="taro";
	console.log('私の名前は'+this.n+'です。');
}
hoge();//私の名前はundefinedです。

なぜなら、hoge内のthisが指すオブジェクトが存在しないからです。これによってhoge内のthisはグローバルオブジェクトつまりwindowを指します。しかし、windowには何も存在しないためundefinedとなるのです。

なので、上記のコードにグローバル変数を追加すると、下記のようにundefinedが出力されることはありません。

var n="次朗";
function hoge(){
	var n="taro";
	console.log('私の名前は'+this.n+'です。');
}
hoge();//私の名前は次朗です。

参考文献