Javascript可以设置上下文(即设置this
):bind
,call
和apply
。
但是当我写一个事件处理程序时:
document.getElementById('myInput').onclick = function ()
{
alert(this.value)
}
<{em> this
P.S。使用jQuery的时候:
object
是( $("#myInput").bind(function (){...})
,bind
或call
)的内部实现
所以当我不使用jQuery时,谁在做呢?
答案 0 :(得分:8)
为什么,DOM / JavaScript当然应该由W3C以这种方式工作。
事件处理程序在特定对象(当前事件目标)的 context 中调用,并随事件对象本身提供。
究竟是怎么回事,我们不知道。这是一个实现细节。
我们所知道的是,W3C定义的语义是以某种方式实现的,但是浏览器的哪个部分实现了这个以及如何,这取决于浏览器开发人员,他们可以按照自己的意愿实施。
答案 1 :(得分:2)
总结所有讨论:
this
时,JavaScript会在函数调用中将o
绑定到o.x()
。f.apply()
和f.call()
)来改变这种行为。onclick
是一种特殊情况,用于调用它的方法是未知的,取决于DOM的实现。答案 2 :(得分:1)
在您的示例中,onclick
处理程序非常简单:DOM元素是对象,您将onclick
属性定义为函数。该函数有效地成为DOMElement / object的一个方法。
当单击该对象时,该函数被调用为该元素的方法,因此这指向其所有者元素。
简单地说,函数执行的上下文与创建的上下文相同(再次:在您的示例中作为DOM元素的方法),除非对函数 object <的引用/ em>被分配给另一个对象,或者在使用call
或apply
&amp;的另一个上下文中调用该函数 object 时当然,除此之外还有更多内容:正如我在上面暗示的那样,函数本身就是对象,据说松散耦合到“owner” 。好吧,实际上他们并没有这样的拥有者,每次调用一个函数时,都会确定其上下文:
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(){}
时,我们看到元素只有拥有对在某个范围内声明的函数表达式的引用(global,namespace-object,doesn'无所谓)。触发click事件时,将使用 reference 来调用处理程序,从而将对元素的引用分配给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
访问它使用onclick
声明的上下文,这要归功于闭包(但这是另一个故事)。关键是,事件使用元素foo
的{{1}}属性引用处理程序。该属性是对函数对象的引用,因此函数对象将其上下文设置为调用的任何对象。
我希望这可以解决我对函数的所有权造成的任何混淆,也许可以确定JS中的上下文是如何确定的。
答案 3 :(得分:1)
答案是说DOM是错误的。
这是JavaScript本身的一部分,作为一种语言。 DOM只是名称表示“文档对象模型”的东西,它就是如何使用JavaScript表示HTML进行操作。与DOM相关的对象遵循标准指定的行为,但这是通过使用JS实现的。这是JS引擎,它与正在使用的任何布局引擎(Gecko,Trident,WebKit,Presto等)进行通信。因此,如果WebKit检测到一个事件,它会将其传递给JS引擎,因为DOM规范指示它可以由JS程序员操纵(这就是为什么你甚至会问这个问题,因为你可以使用它)。 / p>
换句话说,如果你是用JavaScript编写的东西,唯一能理解如何读取和执行的引擎就是JS引擎。该引擎(v8,SpiderMonkey / Jugger / Trace)将从布局引擎接收数据并使用它,以便您可以与它进行交互。同样,另一方面,每当您运行影响布局的代码时,布局引擎都会检测到更改,并且它将更改布局以便用户察觉到更改:即使JS代码可能已启动此更改,是负责布局的布局引擎。
将函数分配给对象时,“this”是什么,只是函数所属的位置。因此,如果您将一个函数分配给对象a的实例,那么只要您在其中使用“this”,所述函数就会引用该函数。
如果您想在实施术语中考虑它,请以这种方式考虑它: 无论何时调用方法,都要首先告诉实例要调用具有N个参数的方法。此实例调用该方法,但将其自身添加到上下文中,如“this”。
在Python中,通过将所有实例方法的第一个参数作为实例本身来更明确地完成。这里是相同的,但实例是隐式传递而不是显式传递。
请记住,实例拥有该方法。当你执行“document.getElementById('something')”时,调用会返回一个对象(碰巧是一个属于DOM的HTMLElement对象,但这与JS与DOM交互的方式一致),然后你要分配该功能作为属性点击。
然后,每当你调用该方法时,JavaScript引擎默认传递实例,就像它传递其他变量一样(如同参数也是在没有你做任何事情的情况下生成的,也是由实现ECMAScript标准的JS引擎完成的)。
我建议检查第63页:
“this关键字计算为当前执行上下文的ThisBinding的值。”
但最重要的是,第68页“函数调用”
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
答案 4 :(得分:0)
这实际上与已经提到的DOM无关,但是当你在一个对象中调用一个函数时,JavaScript是如何设计的。
以此为例:
var myObject = {
id: 1,
onclick: null
}
myObject.onclick = function() {
console.log(this.id);
}
调用myObject.onclick()
会将1
记录到控制台,这意味着myObject
是其上下文。
由于onclick
也是对象的属性,因此this
将是父对象,在您的情况下为HTMLElement
。
答案 5 :(得分:0)
http://dmitrysoshnikov.com/ecmascript/chapter-3-this/#this-value-in-the-function-code
基本上,它是由JavaScript内部人员完成的。
上下文是调用函数的对象,例如
elem.onclick(); // elem === this
然而:
func = elem.onclick;
func() // global === this
答案 6 :(得分:0)
为了便于说明,尽管实现可能不同,但请考虑以下函数
function f() { alert(this.name); }
as
function f(this) { alert(this.name); }
想象一下这个作为一个秘密参数,您可以使用bind,apply和call覆盖它,但通常会被浏览器设置为调用对象。
实施例
var a = {},
b = {};
a.name = "John";
b.name = "Tom";
// "this" param added secretly
function printName( ) {
console.log( this.name )
};
a.printName = printName
b.printName = printName;
当调用printName函数时,浏览器会将“secret” this 参数设置为调用函数。在下面的示例中,这是b,因此“Tom”将打印到控制台。
printName( ); // global context assumed so this === window
b.printName( ); // this === b and outputs "Tom"
printName.call( a ); //this === a and outputs "John"
更多信息here。