深入理解javascript之this
this应该算是javascript语言里面一个非常有意思的对象,因为他在不同环境下的指向都不一样,这很让很多刚开始学javascript的人容易产生混乱,我以前也是这样一片混乱,但是我建议要深入学习javascript语言的朋友,一定要完全理解this对象,因为他的应用非常广泛。今天就总结下这个令人头痛的this在不同情况下指向的问题,下面我的学习笔记总结,希望对一些刚开始学习javascript的人有些帮助。
情况一:函数调用
我们来看下下面一段简单函数代码:
1 | function fn(){ |
上面的结果大家应该没有什么疑问,fn输出作用域内的声明的变量x值。但是我们在把上面的代码稍微改一下,变成这样:
1 | function fn(){ |
上面这段是不是很有意思,我们在fn里面定义了一个this.x,在fn函数内输出了5,但是在fn函数作用域下我们输出x的时候发先居然是0,而不是5。这是因为我们声明的var x = 5;是一个局部变量,外界无法访问,那么输出的0肯定就是this.x=0;操作的结果,因为this.x相当于window.x,这个时候的fn内部的this.x相当于当于声明了一个全局变量x,代码等同于如下:
1 | var x = 0; |
上面这段是不是很有意思,我们在fn里面定义了一个this.x,在fn函数内输出了5,但是在fn函数作用域下我们输出x的时候发先居然是0,而不是5。这是因为我们声明的var x = 5;是一个局部变量,外界无法访问,那么输出的0肯定就是this.x=0;操作的结果,因为this.x相当于window.x,这个时候的fn内部的this.x相当于当于声明了一个全局变量x,代码等同于如下:
1 | var x = 0; |
情况二:在事件处理程序中
我们再来看下面这一段常见的代码,我们定一个按钮来触发我们要操作的回调函数:
1 | var btn = document.getElementById("btn"); |
再来看另一种事件处理程序写法:
1 | var btn = document.getElementById("btn"); |
程序还是报错,上面两段JS的事件绑定处理程序中的this都是指向的ID为btn的按钮,而不是window,很奇怪的设计,你如果要问我为什么我其实也不知道为什么javascript会这样设计this对象;不过大家只要记住上面这个特点以后的工作中就不会犯错了。
情况三:作为对象方法的使用
函数还可以作为某个对象的方法调用,这个时候this就指这个上级对象。
1 | var arg = 0; |
其实上面这段代码还可以转换成下面这种写法:
1 | var arg = 0; |
此时的this也是指向fn这个对象的,上面这个需要特别注意,不要搞混,在面向对象编程的时候非常需要理解这个this在这里的指向。
情况四:作为构造函数时使用
所谓的构造函数简单的理解就是new一个新对象,然后调用他,如下:
1 | function fn(){ |
上面的代码应该大家都很常见,这个时候的this指向的这个new出来的新对象,我们来做个测试,看看this是不是真的指向的是new出来的新对象还是全局(window):
1 | var x = 0; |
大家看上面的结果,this如果指向全局(window)那我们的最后一行代码也将会输出5,而不是0。
情况五:调用apply
apply函数在js在也是扮演这很重的角色,他被很多人用来实现函数的继承,因为这个方法能劫持另外一个对象的方法,继承另外一个对象的属性.
我们把情况三的代码改动成如下:
1 | var arg = 0; |
当调用apply()函数后,我们发现this他将不再指向这个对象本身了,而是指向了全局对象(window)。
那如果我们要通过apply()函数让this指向对象本身怎么办呢?我们可以这样写:
1 | var arg = 0; |
只需在apply()函数指向fn就可以了。