看了网上很多关于javascript this关键字的理解,总觉得不够清晰,经过自己多方测试和查阅资料,写点自己的感悟。有不对的地方,还请大神指正。
大家都知道javascript 中 比较难理解的一个关键字 this,经常不敢确定到底指向哪里了,一般简单的譬如:
var name = 'zengxindong';
function showName(){
return this.name;
}
alert(showName()); //zengxindong
大家都知道是指向window全局对象的属性(变量)name,因为调用showName()实际上就相当于window.showName(),所以this指向window对象。
但是如果复杂点情况呢,有时候就会有点蒙,关键还是没有彻底理解this关键字什么时候初始化,初始化后指向的对象是谁,只要弄清楚了这两个问题,基本上就很清楚this的指向。
在此之前先介绍点周边的概念:
1、函数名是一个指向函数的指针。
2、函数执行环境(this什么时候初始化):当某个函数第一次被调用时,会创建一个执行环境(execution context),并使用this/arguments和其他命名参数的值来初始化函数的活动对象(activation object)。(这里我们不引入此时也会初始化作用域链概念)
3、初始化指向谁:在Javascript中,this关键字永远都指向函数(方法)的所有者。(转载地址:http://www.laruence.com/2009/09/08/1076.html)
但是有了这三个定论(全文都会贯穿这三个理论)了,还需要在复杂的情况下才能深入理解。
有了这三个定论,可以先理解上面那个简单例子:全局函数showName是window对象的一个属性,也就是说showName函数(方法)所有者是window,函数名showName是一个指针,指向函数地址,当直接执行showName()的时候会初始化this,此时this就指向window对象了。
下面就让我们看看闭包(不理解闭包的可以看看:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html)情况下,this关键字指向实例:
var name = 'The window';
var object = {
name:'The object',
getNameFunc:function(){
return function(){
return this.name;
}
}
};
alert(object.getNameFunc()());//The window
这是javascript高级程序设计里面解释:在全局函数中,this等于window,而当函数被当做某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行具有全局性,因此this对象通常指向window(在通过call()或apply()改变函数执行环境的情况下,this就会指向其他对象)
验证测试:
1、我看到这句话之后总觉得心里不太踏实,然后我就改了一下运行:
var name = 'The window';
var object = {
name:'The object',
getNameFunc:function(){
var tmpFunc = function(){
return this.name;
}
return tmpFunc;
}
};
alert(object.getNameFunc()());//The window
这里还是这个结果,最后我又去查了一下,javascript里面函数表达式也属于匿名函数。
2、那我就又改了一下:
var name = 'The window';
var object = {
name:'The object',
getNameFunc:function(){
function tmpFunc(){
return this.name;
}
return tmpFunc;
}
};
alert(object.getNameFunc()());//The window
发现还是"The window"结果,这下该不是匿名函数了吧,所以我的理解是跟匿名函数没关系,因为最后执行的tmpFunc的方法所有者不是object,只有getNameFunc方法所有者是object。
而上面的代码其实可以写成:如下形式:
var tmpFuncPtr = object.getNameFunc();
tmpFuncPtr();(上面说的函数名就是一个指向函数地址的指针)
所以此时this就指向的是window对象,从而弹出window对象name属性"The window"。
3、然后我又做了如下测试:
var name = 'The window';
var object = {
name:'The object',
getNameFunc:function(){
return object1.getNameFunc;
}
};
var object1 = {
name:'The object1',
getNameFunc:function(){
return this.name;
}
};
alert(object.getNameFunc()());//The window
结果还是"The window",哈哈哈,再看下面稍微修改一下:
var name = 'The window';
var object = {
name:'The object',
getNameFunc:function(){
return object1.getNameFunc();
}
};
var object1 = {
name:'The object1',
getNameFunc:function(){
return this.name;
}
};
alert(object.getNameFunc());//The object1
这里的结果就是"The object1"了。
我分析一下原因啊,还是上面的三个定论作为依据:
弹出结果为"The window"的那段程序,object1.getNameFunc只是引用了object1对象的getNameFunc属性,也就是一个函数的地址。此时没有调用函数,所以也就不会初始化this关键字。最后调用实际上还是相当于是:
var tmpFuncPtr = object1.getNameFunc;
tmpFuncPtr();//所以还是指向window全局对象
而弹出结果为"The object1",此时object1.getNameFunc()相当于是调用object1对象的getNameFunc方法,此时会初始化this关键字,而getNameFunc方法的所有者就是object1,this指向object1,所以调用object1.getNameFunc()返回的是object1的name属性,也就是"The object1"
4、然后再继续测试:
var name = 'The window';
var object = {
name:'The object',
getNameFunc:function(){
return object1.getNameFunc;
}
};
var object1 = {
name:'The object1',
getNameFunc:function(){
return function(){
return this.name;
}
}
};
alert(object.getNameFunc()()());//The window
这个有了上面的介绍大家应该也能理解了。
总算是彻底搞清楚this关键字了,以前总觉得不踏实,不知道到底指向哪里。希望大家看了我这篇文章能有所收获。有不对的地方,也希望大家能耐心指正