概要
this キーワードはコンテキストオブジェクト (カレントオブジェクト) を参照します。一般的に、メソッド内では this は呼び出し元オブジェクト (calling object)を参照します。
構文
this
説明
this は読み取り専用です。
thisを使うと現在のコンテキストオブジェクトへの参照を得ることができ、その実行コンテキストのプロパティやメソッドを this を通して (this.member のようにして) 参照できます。コンテキストオブジェクトは関数に渡される「隠しパラメータ」とみなす事が出来ます。this が渡されるのには 3 通りの方法があります。
| 型 | トリガ | this |
| メソッドの呼び出しで暗黙的に | object.method( . . . ) |
object |
| Function.prototype.call を経由して明示的に | function.call(object, . . . ) |
object |
| Function.prototype.apply を経由して明示的に | function.apply(object, [. . .]) |
object |
上記のいずれの方法も取られなければ、グローバルオブジェクトがコンテキストオブジェクトとして渡されます。これは、例えば関数外部のトップレベルコードで this が使われた時や、func(arg1, arg2); のようにオブジェクトに付随せずに関数が呼ばれた時などです。
ECMAScript バインディングを通して DOM を操作する場合、JavaScript を使ってイベントハンドリングを行うことがよくありますが、イベントハンドリングでは実行コンテキストが特殊な方法で扱われます。
メソッドの束縛
this は関数に「渡される」のであって、関数に固定されている訳ではありません。言い換えると、メソッドはそれをメソッドとして持つオブジェクトに束縛されているのではなく、オブジェクトによって参照されているだけです。
束縛の概念を説明するために、次の例を考えます。
function Car(brand) {
this.brand = brand;
}
Car.prototype.getBrand = function() {
return this.brand;
}
var foo = new Car("toyota");
println(foo.getBrand()); // println 関数は定義済みとする
これは予想通り "toyota" を出力します。
var brand = "not a car"; var bar = foo.getBrand; bar();
これは "toyota" ではなく "not a car" を返します。ここでの this は、グローバルオブジェクトであり、ブラウザ環境では window です。なぜなら bar() が呼び出されたコンテキストがグローバルオブジェクトだからです。グローバルオブジェクトにも brand というプロパティがあり、それは "not a car" という値を持っています。もしグローバルオブジェクトが brand というプロパティを持っていなければ、代わりに undefined が返されていたことでしょう。
ここからわかるように、bar は foo とは何のつながりもありません。オブジェクトは関数を参照するプロパティを持つ事が出来ますが、その関数はそのオブジェクトに所属 している訳ではありません。具体的に言うと、この関数内の this は getBrand の定義時に自動的に foo に置き換えられるわけではありません。そうではなく、this は関数の呼び出し元から与えられます。つまり、foo.getBrand() という式によって、foo が this として foo.getBrand に参照される関数に渡されるということです。以下の式はすべて等価です。
foo.getBrand(); bar.call(foo); foo.getBrand.call(foo);
このようにメソッドが束縛されないのは意図された挙動です。これにより、メソッドを「共有」したり、オブジェクトからオブジェクトへ「移動」する事が出来ます。前の例に続けて次のような文を考えます。
function Airplane(brand) {
this.brand = brand;
}
var plane = new Airplane("boeing");
plane は getBrand メソッドを持っていませんが、brand プロパティを持っており、Car の getBrand メソッドと互換性があります。したがって Car.prototype.getBrand によって参照されている関数は、Airplane によって生成されるオブジェクトと Airplane.prototype のどちらとでも「共有」する事が出来ます。