Javascript は遅延バインディング言語です。実際、バインディングは非常に遅いです。this
コンパイル時にバインドされないだけでなく、実行時にもバインドされません (他のほとんどの遅延バインディング言語が行うように)。JavaScript では、this
呼び出し時にバインドされます。
バインディング ルールは他のほとんどの OO 言語とはかなり異なるため、javascript に慣れていない多くの人々を混乱させるようです。
this
基本的に、コード内で使用する方法と場所は、 のthis
動作に影響しません (スタンドアロン関数、オブジェクト リテラルなどであるかどうかは関係ありません)。値を決定するのthis
は、関数の呼び出し方法です。
ルールは次のとおりです。
1 - 関数がコンストラクターとして呼び出されると、新しいオブジェクトが作成され、this
そのオブジェクトにバインドされます。例えば:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
2 - オブジェクト メソッドとして呼び出されたthis
場合、メソッドが属するオブジェクトを参照します。基本的に、最後のドットの前の名前。例えば:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
3 - 関数の外で使用される場合、または関数がメソッドとして呼び出されない場合this
、グローバル オブジェクトを参照します。JavaScript の仕様では、存在するということ以外にグローバル オブジェクトに名前を付けていませんが、ブラウザでは伝統的に と呼ばれていwindow
ます。例えば:
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
4 - イベント ハンドラー (onclick など) ではthis
、イベントをトリガーした DOM 要素を参照します。setTimeout
またはXMLHTTPRequest
、やなどの DOM に関連付けられていないイベントの場合this
は、グローバル オブジェクトを参照します。例えば:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
5 - 最後に、call()
またはapply()
メソッドのいずれかを使用して関数が呼び出されるとthis
、何にでも再割り当てできます (google "mdn function.prototype.call")。このように、JavaScript の任意のオブジェクトは、別のオブジェクトのメソッドを借用/盗むことができます。例えば:
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
最新の JavaScript 実装でFunction.bind()
は、別のルールがあります。
6 - メソッドを使用して、関数をthis
オブジェクトに明示的にバインドすることもできますbind()
。メソッドは、に渡された引数にバインドされている関数のbind
新しいインスタンスを返します。例えば:this
bind
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
ECMAscript 5 では、メソッドとして呼び出されないか、call または apply で呼び出されない関数で this の意味を変更する厳密モードが導入されたため、新しいルールを追加する必要があります。
7 - 厳密モードの場合this
、グローバル オブジェクト (ブラウザーのウィンドウ) を参照できません。したがって、関数がメソッドとして呼び出されていない場合、またはorthis
を介して手動で何かにバインドされていない場合は、次のようになります。call
apply
bind
this
undefined
"use strict";
function foo () {
return this;
}
foo(); // returns undefined instead of the global object
ECMAscript 6 でアロー関数が導入されました。アロー関数は、早期にバインドすることで、これがどのように動作するかを変更します。
8 - アロー関数でthis
は、関数が宣言された時点でバインドされます。したがってthis
、次のコードでは:
var x = () => {return this};
関数が次のコードのように宣言されているかのように動作します。
var x = function () {return this}.bind(this);
this
in アロー関数は関数が宣言された時点でバインドされるため、継承を使用する場合はアロー関数を使用できないことに注意してください。これthis
は、関数内の が常に親オブジェクトを指し、子オブジェクトを指すことはないためです。つまり、矢印関数で継承を機能させる唯一の方法は、親オブジェクトのすべての矢印関数をオーバーライドすることです。