在JavaScript中this變數是一個令人難以摸清的關鍵字,this可謂是非常強大,充分了解this的相關知識有助於我們在編寫物件導向的JavaScript程式時能夠遊刃有餘。
1. 一般用處
對於this變數最要的是能夠理清this所引用的物件到底是哪一個,也許很多資料上都有自己的解釋,但有些概念講的偏繁雜。而我的理解是:首先分析this所在的函式是當做哪個物件的方法呼叫的,則該物件就是this所引用的物件。
示例一
var obj = {}; obj.x = 100; obj.y = function() { alert( this.x ); };//this指向的物件是obj obj.y(); //彈出 100
這段程式碼非常容易理解,當執行 obj.y() 時,函式是作為物件obj的方法呼叫的,因此函式體內的this指向的是obj物件,所以會彈出100。
示例二
var checkThis = function() { alert( this.x); //this的指向是window下的 }; var x = 'this is a property of window'; //變數提升 var obj = {}; obj.x = 1000; obj.y = function(){ alert( this.x ); }; // this指向物件是 obj,呼叫obj.y();this的指向物件是obj
var obj2 = obj.y; //由於obj2();直接呼叫,這時this的指向是window物件下
obj.y(); //彈出 1000
checkThis(); //彈出 'this is a property of window
obj2(); //彈出 'this is a property of window
這裡為什麼會彈出 'this is a property of window',可能有些讓人迷惑。在JavaScript的變數作用域裡有一條規則“全域性變數都是window物件的屬性”。當執行 checkThis() 時相當於 window.checkThis(),因此,此時checkThis函式體內的this關鍵字的指向變成了window物件,而又因為window物件又一個x屬性( 'this is a property of window'),所以會彈出 'this is a property of window'。
上面的兩個示例都是比較容易理解的,因為只要判斷出當前函式是作為哪個物件的方法呼叫(被哪個物件呼叫)的,就可以很容易的判斷出當前this變數的指向。
2. this.x 與 apply()、call()
通過call和apply可以重新定義函式的執行環境,即this的指向,這對於一些應用當中是十分常用的。
示例三:call()
function changeStyle( type , value ){ this.style[ type ] = value;//this指向是window物件下 } var one = document.getElementById( 'one' ); changeStyle.call( one , 'fontSize' , '100px' );//call庫函式能改變this指向,即this指向"one"這個物件, 第一個引數是this引用的物件"one",第二個引數是style下的屬性名,第三個引數是style下的屬性值 changeStyle('fontSize' , '300px'); //出現錯誤,因為此時changeStyle中this引用的是window物件,而window並無style屬性。
注意changeStyle.call() 中有三個引數,第一個引數用於指定該函式將被哪個物件所呼叫。這裡指定了one,也就意味著,changeStyle函式將被one呼叫,因此函式體內this指向是one物件。而第二個和第三個引數對應的是changeStyle函式裡的type和value兩個形參。最總我們看到的效果是Dom元素one的字型變成了20px。
示例四:apply()
function changeStyle( type , value ){ this.style[ type ] = value; } var one = document.getElementById( 'one' ); changeStyle.apply( one , ['fontSize' , '100px' ]);//apply庫函式能改變this指向,即this指向"one"這個物件, 第一個引數是this引用的物件"one",第二個引數是一個陣列,包括style下的[屬性名,屬性值] changeStyle('fontSize' , '300px'); //出現錯誤,原因同示例三
apply的用法和call大致相同,只有一點區別,apply只接受兩個引數,第一個引數和call相同,第二個引數必須是一個陣列,陣列中的元素對應的就是函式的形參。
3. 無意義(詭異)的this用處
示例五
var obj = { x : 100, y : function(){ setTimeout( function(){ alert(this.x); } //這裡的this指向的是window物件,並不是我們期待的obj,所以會彈出undefined , 2000); } }; obj.y();
如何達到預期的效果
var obj = { x : 1000, y : function(){ var _self = this; //注意 : 給this賦值, 這裡改變了 this 的指向,指向了 0bj setTimeout( function(){ alert(_self.x); }//setTimeout改變this的指向,變為window下,為了不改變指向,只能用_self=this,臨時變數儲存 , 2000); } }; obj.y(); //彈出1000var obj = {
x : 1000,
y : function(){
alert(this.x); //這裡的this指向的是obj物件,並不是我們期待的obj,所以會彈出1000
}
};
4. 事件監聽函式中的this
var one = document.getElementById( 'one' ); one.onclick = function(){ alert( this.innerHTML ); //this指向的是one元素 };
5. 總結
以上可以歸納為:“this所指的就是直至包含this指標的上層物件”
呼叫形式 | this指向 |
---|---|
普通函式 | 全域性物件window |
物件的方法 | 該物件 |
建構函式 | 新建構函式 |