在你的例子中,一个
onclick
处理程序非常简单:DOM 元素就是一个对象,你正在定义
onclick
属性为一个函数。该函数有效地成为该 DOM 元素/对象的方法。
当该对象被点击时,该函数作为该元素的方法被调用,因此 this 指向其所有者,即该元素。
简而言之,函数执行的上下文与创建它的上下文相同(再次强调:在你的例子中,它是 DOM 元素的方法),除非将对函数对象的引用分配给另一个对象,或者在另一个上下文中使用 call
或 apply
等调用该函数对象。
当然,这还有更多的内容:正如我上面暗示的那样,函数本身也是对象,并且被称为与其“所有者”松散耦合。实际上,它们没有像这样的所有者,每次调用函数时,都会确定其上下文:
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()
{
var that = this;
console.log(this);
return function(e)
{
console.log(this === that);
console.log(this);
console.log(that);
};
})();
因此,处理程序在全局上下文中声明,处理程序可以使用闭包(但这是另一个故事)通过that
访问其声明的上下文。重点是,事件使用元素foo
的onclick
属性引用处理程序。该属性是对函数对象的引用,因此函数对象将其上下文设置为调用所做的任何对象。
我希望这能澄清我在函数“所有权”方面引起的任何困惑,也许还有JS中如何确定上下文的问题。