JS中this關鍵字很常見,可是它彷佛變幻莫測,讓人抓狂。這篇文章就來揭示其中的奧祕。html
藉助阮一峯老師的話:它表明函數運行時,自動生成的一個內部對象,只能在函數內部使用。這句話看似日常,但是要很是注意三個字:「運行時」,這說明this關鍵字只與函數的執行環境有關,而與聲明環境沒有關係。也就是這個this到底表明的是什麼對象要等到函數運行時才知道,有點相似函數定義時的參數列表只在函數調用時才傳入真正的對象。理解了這一點對後面this關鍵字規律的掌握有很大幫助。數組
this關鍵字雖然會根據環境變化,可是它始終表明的是調用當前函數的那個對象。這就引出了JS中函數調用的問題。在JS中調用函數的模式能夠分爲4種: 方法調用模式、函數調用模式、構造器調用模式、apply調用模式。這些模式在如何初始化關鍵參數this上存在差別。瀏覽器
當函數被保存爲一個對象的屬性時,它就可稱爲這個對象的方法。當一個方法被調用時,this被綁定到這個對象上。若是調用表達式包含一個提取屬性的動做(. 或 []),那麼它被稱爲方法調用。例如:app
var name = "window"; var obj = { name: "kxy", sayName: function() { console.log(this.name); } }; obj.sayName(); //kxy
sayName函數做爲對象obj的方法調用,因此函數體中的this就表明obj對象。函數
當一個函數並不是一個對象的屬性時,那麼它就是被當作函數來調用的。在此種模式下,this被綁定爲全局對象,在瀏覽器環境下就是window對象。例如:this
var name = "window"; function sayName() { console.log(this.name); } sayName();
sayName以函數調用模式調用,因此函數體中的this表明window對象。prototype
若是在一個函數前面加上new關鍵字來調用,那麼就會建立一個鏈接到該函數的prototype成員的新對象,同時,this會被綁定到這個新對象上。這種狀況下,這個函數就能夠成爲此對象的構造函數。例如:htm
function Obj() { this.name = "kxy"; } var person = new Obj(); console.log(person.name); //kxy
Obj做爲構造函數被調用,函數體內的this被綁定爲新建立的對象person。對象
在JS中,函數也是對象,全部函數對象都有兩個方法:apply和call,這兩個方法可讓咱們構建一個參數數組傳遞給調用函數,也容許咱們改變this的值。例如:ip
var name = "window"; var person = { name: "kxy" }; function sayName() { console.log(this.name); } sayName(); //window sayName.apply(person); //kxy sayName.apply(); //window
當以函數調用模式調用sayName時,this表明window;當用apply模式調用sayName,並給它傳入的第一個參數爲person時,this被綁定到person對象上。若是不給apply傳入任何參數,則this表明window。
自此,函數調用的4種模式就都介紹完了,this的綁定規律也就是以上幾種,萬變不離其宗。爲了簡單明瞭的介紹4種模式,以上的例子都比較簡單,那麼下面就跟我一塊兒作一個稍複雜的練習,檢驗下本身是否真正掌握了this綁定對象的方法吧!
var name = "window"; function showName() { console.log(this.name); } var person1 = { name: "kxy", sayName: showName } var person2 = { name: "Jake", sayName: function() { var fun = person1.sayName; fun(); } } person1.sayName(); //kxy person2.sayName(); //window
首先心中時刻提醒本身this是在函數執行時被綁定的,不要被任何賦值語句打亂陣腳。
先看第一個執行語句:person1.sayName(); 首先肯定這是方法調用模式,對象爲person1,再看sayName被賦值爲全局函數對象showName,在showName執行時,this綁定的是person1,因此結果爲」kxy」。
再看第二個執行語句:person2.sayName(); 這仍是方法調用模式,對象爲person2,調用的是它的sayName方法。再看sayName函數體,發現函數體最終執行的函數是fun,fun是用函數調用模式調用的。而fun最終也被賦值爲showName函數,由於fun是用函數調用模式調用的,因此這裏的this綁定爲window,結果爲」window「。
怎麼樣,你作對了嗎?