在web項目中Javascript是一門必需要掌握的動態語言,基於Javascript的框架大多離不開不了最基礎的Javascript的用法和原理。本文主要是總結一下Javascript中那萬惡的this關鍵字。javascript
開門見山,拋出一個觀點:「Javascript中this永遠是指向調用它的對象」。下面我會舉3個最有表明性的例子來驗證個人這個觀點。java
var x = 1; function testThis(){ console.log(this.x); } testThis(); // 這裏聲明瞭一個全局變量x,一個全局方法,這兩個對象都綁定在Window上,因此當運行testThis()的結果就是取Window對象上的x成員,結果是1 var o={}; o.x = 5; o.method = testThis; o.method(); // 此時,咱們講o對象的method指向了testThis, 當調用它的時候,this指向調用他的對象,這是x就是去o對象的x,結果是5
這個例子十分基礎,也就是常見的對象調用方法的時候,方法裏面的this就是指向調用他或者是擁有他的對象web
var x = 2; function test(){ this.x = 1; } var o = new test(); console.log(o.x); // 1 //這就是javascript中的構造函數,經過new來建立一個實例,這裏取的值是綁定在對象o裏面的x,因此是1 //下面這個例子是Angular中的Service,你能夠直接理解成他會經過第二個參數new一個單例對象 app.service("MyService", function ($http, $modal) { this.test = function() { console.log(this); test2(); } function test2() { console.log(this) } } MyService.test() // 打印 MyService {test: function} 和 Window {}
//這裏log出來雖然test2()能夠被test1()調用,但它其實並不屬於Service, 因此若是test2裏面調用this,就會出現常見的錯誤,哎呀媽呀,咋調不了本身的方法?!
這個例子咱們項目中常常出現,並且很難解釋清楚,就像還有人問我爲何controller中不直接使用this,而是要用$scope來綁定方法和變量,固然用this可以取代部分$scope,可是不免遇到this的上下文不一樣引發的一系列問題。這個問題的關鍵就是test2方法並不屬於對象Service,可是因爲在service閉包(closure)裏面,他能夠被Service調用,因此test2裏面的this就不是指向Service,從而調用Service裏面的其餘方法就會報錯。閉包
function test(){ console.log(this.x); } var o={}; o.x = 1; o.m = test; o.m.apply({x:5}); //5 o.m.call() // undefined //經過apply/call來指定調用函數的this做用上下文,都是指用參數對象來調用o對象的函數,默認參數是Global
其實經過這個例子,你們就已經能夠看到this的指向是不肯定的,this值在進入上下文時肯定,而且在上下文運行期間永久不變。上面的例子改變this的上下文,致使兩次結果不一致也是最好的證據。app
本文最大的做用就是若是看完本文你可以理解this爲何有時候會跟本身指望不同,並且能獲得一個避免這樣問題發生的解決方案,那個人目的就達到了。很幸運你能看到這裏,解決方案呈現給你們:就像Angular要將屬性和方法給你提供一個$scope來綁定屬性,也像coffeeScript會在對象一開頭有這麼個賦值「 _this = this」,咱們在本身的js實踐中不妨定義"val self = this",在以後的做用域裏面用self來操做對象的屬性,這是解決之道。框架