this指针,在Java EE等开发语言中叫做“上下文对象”,但是在JavaScript中情况完全不同,不能把Java EE中对this的理解带到JavaScript中来。
言归正传,在JavaScript中,this代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。也就是说this跟函数的声明没有任何关系,只有在函数或者方法被调用时才知道this的值。this关键字会根据环境变化,但是它始终代表的是调用当前函数的那个对象,记住一点:谁调用这个函数或方法,this关键字就指向谁。在JavaScript中函数的调用模式大致分为以下4种:
1、函数调用模式
即一个函数并非某个对象的属性时,那么它就是被当做函数来调用的。在此种模式下,this被绑定为全局对象,在浏览器环境下就是window对象。例
function sayName() {
this.name = "tang";
console.log(this.name);
}
sayName();//tang
由于this===window对象,上面的写法等同于:
var name = "tang";
function sayName() {
console.log(this.name);
}
sayName();//tang
注意和下面的写法区分
function sayName() {
var name = "tang";
console.log(this.name);
}
sayName();ReferenceError资源不存在错误(由于在window对象不存在name属性)
2、方法调用模式
当函数是某个对象的属性时,它就可称为这个对象的方法。当一个方法被调用时,this被绑定到这个对象上。例
var name = "window";
var obj = {
name: "obj",
sayName: function() {
console.log(this.name);
}
};
obj.sayName(); //obj
此时的this指向obj对象
注意和下面的写法区分
var name = "window";
var obj = {
name: "obj",
sayName: function() {
console.log(this.name);
}
};
var ss = obj.sayName;
ss(); //window
这种情况相当于在全局作用域调用,是函数调用而不是方法调用!
3、构造函数模式
当函数被作为构造函数调用时(即通过函数new新的函数实例对象),this被绑定到新创建的函数对象上。例
function Obj() {
this.name = "kxy";
}
var person = new Obj();
console.log(person.name); //kxy
4、call/apply调用模式
JavaScript中,函数可以通过call和apply方法在特定的执行环境中自调,区别在于call传递多个参数,apply传递参数数组。不管怎么样,这两个函数的第一个参数都是特定的执行环境。下面以apply为例
var name = "window";
var person = {
name: "kxy"
};
function sayName() {
console.log(this.name);
}
sayName(); //window
sayName.apply(person); //kxy(传递person作为执行环境)
sayName.apply(); //window(不传参数是默认的执行环境是全局环境window)
除了上面常见的4中函数调用模式外,还有几种特殊调用,this均指向全局变量window
1、匿名函数调用
var name = "Bob";
var nameObj ={
name : "Tom",
showName : function(){
alert(this.name);
},
waitShowName : function(){
!function(__callback){
alert(this.name);
}();
}
};
nameObj.showName(); //Tom
nameObj.waitShowName(); //Bob
2、setTimeout和setInterval
var name = "Bob";
var nameObj ={
name : "Tom",
showName : function(){
alert(this.name);
},
waitShowName : function(){
setTimeout(function(){
this.showName();
}, 1000);
}
};
nameObj.waitShowName(); //Bob
如果想输出期望值,不凡先保存this的值
var name = "Bob";
var nameObj ={
name : "Tom",
showName : function(){
alert(this.name);
},
waitShowName : function(){
var that = this;
setTimeout(function(){
that.showName();
}, 1000);
}
};
nameObj.waitShowName(); //Tom
无论JavaScript表达式多复杂,嵌套调用多少次,都离不开以上提到的几种情况,只要层层分析,总能得到期望值!!!