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表達式多複雜,嵌套調用多少次,都離不開以上提到的幾種情況,只要層層分析,總能得到期望值!!!