淺顯易懂的理解JavaScript中的this關鍵字

shirleyYing發表於2017-01-06

在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();    //彈出1000

var obj = {
  x : 1000,
  y : function(){
    alert(this.x); //這裡的this指向的是obj物件,並不是我們期待的obj,所以會彈出1000
  }
};
 
obj.y();
注意:setTimeout,setInterval,ajax機制(callBack回撥函式)能夠使this改變成window物件

4. 事件監聽函式中的this

var one = document.getElementById( 'one' );
one.onclick = function(){
    alert( this.innerHTML );    //this指向的是one元素
};

5. 總結

以上可以歸納為:“this所指的就是直至包含this指標的上層物件”

呼叫形式this指向
普通函式 全域性物件window
物件的方法 該物件
建構函式 新建構函式

相關文章