this是Javascript语言的一个关键字,它是一个指针,根据不同情形下指向不同的对象,随着函数使用场合的不同,this的值会发生变化。
记住一条:当function被作为method调用时,this指向调用对象。另外,JavaScript并不是OO的,而是object based的一种语言。之所以你会觉得this用起来混乱,是因为你还没理解JavaScript的诸如全局对象、event handler等一些机制。
this指向变化通常有以下几种情形:
情况一:纯粹的函数调用[作为method调用]
JavaScript代码
- function test(){
- this.x = 1;
- alert(this.x);
- }
- test(); // 1
以上function属于全局性调用,因此this就代表全局对象Global,为了证明它指向window 我们在window下给设置一个变量并去掉内部的赋值:
JavaScript代码
- var x = 1;
- function test(){
- alert(this.x); //取window下的x
- }
- test(); // 1
- var x = 1;
- function test(){
- this.x = 0; //this指针依然是window,只是重新复制而已
- }
- test();
- alert(x); //0
情况二:作为对象方法的调用
作为对象的方法调用时,这时this指针就指这个对象,而不是window!
JavaScript代码
- function test(){
- alert(this.x);
- }
- var o = {};
- o.x = 1;
- o.m = test;
- o.m(); // 1
为了验证以下此时this能不能指向window我们做如下改动:
JavaScript代码
- var x='windowX';
- function test(){
- alert(this.x);
- }
- var o = {};
- //o.x = 1;
- o.m = test;
- o.m(); // undefined -->可见this不可能指向window
情况三 作为构造函数调用
所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。
JavaScript代码
- function test(){
- this.x = 1;
- }
- var o = new test();
- alert(o.x); // 1
同样,为了验证以下此时this能不能指向window我们做如下改动:
JavaScript代码
- var x='windowX';
- function test(){
- this.x = 1;
- }
- var o = new test();
- alert(o.x); // 1 -->可见this不可能指向window
- alert(x); // windowX
情况四 apply调用
apply()是函数体的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数
JavaScript代码
- var x = 'windowX';
- function test(){
- alert(this.x);
- }
- var o={};
- o.x = 1;
- o.m = test;
- o.m.apply(); //windowX m函数的apply更改了调用对象-->window
apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为windowX,证明this指的是全局window对象。
如果把最后一行代码修改为:
JavaScript代码
- o.m.apply(o); //1 运行结果就变成了1,证明this又指向了默认的o对象
练习测试题:
JavaScript代码
- /******** this指针及变量提升的问题 ********/
- var foo='windowFoo';
- function main(){
- alert(foo); //第一个alert,一般规则是先查找当前内部变量有没有,有则取没有找上一层
- var foo = 2;
- alert(this.foo); //第二个alert,
- this.foo = 3;}
注明:首先说下window下直接调用main()方法 this==window
测试1: var m1=main(); //作为普通函数调用或者直接调用main()
第一个alert属于特殊情况,内部有同名变量存在且在后边定义,涉及到了变量提升,因此输出:undefined
第二个alert属于查找this指针对象下的属性,this指针指向window固输出:windowFoo 而不是后边的3
测试1: var m2=new main(); //作为构造函数实例化之后调用
第一个alert 输出undefined因为构造函数实例化后this指向该对象,不会变化
第二个alert 输出undefined因为this.foo被实例化对象继承后等同于增加一个属性方法,且在alert之后,因此输出:undefined