|
下图是在ASP.NET中为button挂上客户端onclick事件的两种办法:图中的2和3/1。 结果发现两种方式调用同样一个函数clickMe,this却不一样。
如果采用3或1的做法,那么点击button1后将alert出[object DOMWindow];而采用2的做法,将alert出 [object HTMLInputElement](在chrome下测试。)
显然,在1的做法中,this指向DOMWindow,也就是全局的object——global;而2的做法中,this指向Button1这个元素。
为什么呢?
(注:对于3这种通过Attribute来声明处理程序的方式,button的onclick不是指向clickMe函数,而是指向一个被自动创建的匿名函数,该匿名函数以Attribute的值(也就是"clickMe();")作为函数体——也就是等价于1。)
简单的答案
基于类的OO语言(比如C#)中,函数总是声明在一个类中,函数内部的this指向该类的当前实例。而JS中,函数是第一等公民(它不会声明为别的东西的一部分),所以this跟函数是如何声明的无关,跟函数是怎么被调用的有关。
方式1和2对clickMe的调用,不同之处在于:1中clickMe是被button1.onclick所指向的函数调用的,2中clickMe是作为button1.onclick属性直接调用的。因此对于clickMe函数,1中的this指向“拥有”clickMe函数的对象——global(DOMWindow),而2中的this指向“拥有”onclick属性的对象——button1。
可惜对像我这种写JS写的不多的人来说,总是记不住这个简单答案,因为它只告诉我what,没有告诉我why。本文试图从ECMAScript官方文档出发,从原理上说明:在不同的场合中,函数的this到底是什么?
call和apply
首先明确一点,在最正常的情况下,我们这样调用:Func(),这时this是由JavaScript来确定的,这也是本篇要研究的主题。而如果用Func.call(thisArg, arg1, arg2, ...)或者Func.apply(thisArg, [arg1, arg2, ...])来调用时,this是我们自己传进去的(作为call或apply的第一个参数)。如果我们不传this进去,或者传null进去,会怎样?这时this将会是global object。
函数作为构造器时的this
先从简单的说起。所谓构造器,就是用new关键字来调用函数,在这篇关于new关键字的玄机的文章中有说到。看下面的注释,可以知道,A函数里的this这时就是a。
function A() {this.x = 1;}var a = new A(); //这行代码大概等价于下面两行
it知识库:我的JavaScript之旅——this到底是啥?,转载需保留来源!
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。