在JavaScript中,this用于存取与函数相关联的对象,在JAVA和C++等面向对象的语言里,this变量指向对象的当前实例,而在JavaScript里稍微有点区别:this所引用的对象被存为函数上下文,它不是由如何声明函数,而是由如何调用函数来决定的。下面我们分几种情况来讨论this是如何指向的。
1,普通的全局函数调用,看如下代码:
这段代码的结果是在一个弹出框里输出"hello",也许有人会问alert函数不是直接调用吗?应该是alert("hello");,不错通常全局的函数都是直接调用的,就像上面的直接调用hello()函数一样,其实之所以能够直接调用是因为所有的全局函数都是window对象的一个属性,上面的代码其实可以写成
如果还是不确定你可以通过执行alert(window.hello);来看一下输出,输出结果就是hello函数。而调用window对象的属性或方法是不需要加前缀的。在这里hello()的调用者是window对象,因此this指向window对象,所以this.alert("hello");是合法的。因此所有的全局函数在被直接调用时它的this都指向它的调用者:window对象。
2. 内联型事件处理函数,看如下代码:
第一个输出是"undefined",第二个输出是:function onclick(event){hello();}。先看第二个输出,我们使用内联型事件注册方式时,浏览器做了两件事:1,将赋给onclick的js代码(我们这里hello();,其实这里可以写任意的js代码)作为函数体生成一个函数,例如function onclick(event){hello();};2,为当前元素对象(我们这里是P对象)创建一个onlick属性,并将刚才生成的函数赋值给onlick属性,最终的代码应该是p.onclick = function onclick(event){hello();}。因此当点击发生时,应该是调用p.onclick(),然后在onclick函数里调用hello();这里hello()函数的调用方式应该是window.hello();,所以hello()函数的调用者应该是window对象,window对象是没有id的,所以第一个输出是"undefined"。因此在内联型的事件注册方式中,响应函数的this通常指向window对象。
如果想在内联型事件函数里访问当前对象又该怎么办呢?看如下代码:
输出结果是"abcd",说明obj是指向当前响应事件的对象的,感兴趣的朋友可以想一下为什么可以这么做。
3. 传统型事件函数,看如下代码:
这里的第一个输出为abcd,第二个输出function hello() {alert(this.id);alert(this.onclick)}。其实上面的代码做了两件事:1,为window对象创建了window.hello = function hello() {alert(this.id);alert(this.onclick)}的函数对象属性;2,将window.hello属性的值赋给p.onclik属性,因为JS的对象复制其实就是引用的复制,所以window.hello和p.onclick都指向同一个值function hello() {alert(this.id);alert(this.onclick)},所以如果是响应点击事件,则函数hello()的this指向p对象(因为调用方式是p.onclick()),而如果是直接调用如hello();或window.hello()(参照上面第一条),则函数hello()的this指向window对象。
4. 通过apply()和call()方法来调用函数
比如我们使用call来调用上面的hello()方法,我们先创建一个对象,var obj = {name: 'Boris'};hello.call(obj);这时在hello函数中this指向obj,因为apply和call方法会把函数的this上下文用传进去的对象替换掉。
参考文献:
2. 《jQuery实战》
3. 《JavaScript核心教程》