あなたの例では、onclick
ハンドラーのそれは完全に簡単です.DOM要素はオブジェクトであり、onclick
プロパティを関数として定義しています. その関数は事実上、その DOMElement/オブジェクトのメソッドになります。そのオブジェクトがクリックされると、関数はその要素のメソッドとして呼び出されるため、 this はその所有者
である要素を指します。
簡単に言えば、関数オブジェクトへの参照が別のオブジェクトに割り当てられていない限り、関数が実行されるコンテキストは、作成されたコンテキストと同じです (繰り返しますが、DOM 要素のメソッドとしての例では)。その関数オブジェクトcall
がor apply
& coを使用して別のコンテキストで呼び出されたとき。
もちろん、これにはもう少し多くのことがあります: 上でほのめかしたように、関数はそれ自体がオブジェクトであり、それらの「所有者」に疎結合されていると言われています。実際には、関数が呼び出されるたびに、そのコンテキストが決定されます。
var foo = someObject.someFunction;//reference to method
someObject.someFunction();//this === someObject, context is the object preceding the function
foo();//implies [window].foo(); ==> this is window, except for strict mode
@wroniasty が指摘したように、所有権についての私の話は少し混乱するかもしれません。問題は、関数はオブジェクトであり、何にも所有されていないということです。オブジェクトにメソッドが割り当てられると、そのオブジェクトが実際に所有するのは、特定の関数オブジェクトへの参照だけです。その関数がその参照を介して呼び出されるとthis
、呼び出し元の参照を所有していたオブジェクトを指します。
これを に適用するとelem.onclick = function(){}
、要素が何らかのスコープで宣言された関数式への参照のみを所有していることがわかります (グローバル、名前空間オブジェクトは関係ありません)。クリック イベントが発生すると、その参照を使用してハンドラーが呼び出され、要素への参照が に割り当てられthis
ます。明確にするために:
document.getElementById('foo').onclick = (function()
{//This function returns the actual handler
var that = this;//closure var
console.log(this);//logs window object
//defined in global context
return function(e)//actual handler
{
console.log(this === that);//false
console.log(this);//elem
console.log(that);//window
};
})();//IIFE
そのため、ハンドラーはグローバル コンテキストで宣言され、that
クロージャーのおかげで、ハンドラーは using で宣言されたコンテキストにアクセスできます (ただし、それは別の話です)。ポイントは、イベントonclick
が element のプロパティを使用してハンドラを参照することfoo
です。そのプロパティは関数オブジェクトへの参照であるため、関数オブジェクトはそのコンテキストを、呼び出しを行ったオブジェクトに設定します。
これにより、関数の所有権、およびおそらく JS のコンテキストがどのように決定されるかに関して私が引き起こした混乱が解消されることを願っています。