玩轉Javascript this用法


  在web項目中Javascript是一門必須要掌握的動態語言,基於Javascript的框架大多離不開不了最基礎的Javascript的用法和原理。本文主要是總結一下Javascript中那萬惡的this關鍵字。

  開門見山,拋出一個觀點:“Javascript中this永遠是指向調用它的對象”。下面我會舉3個最有代表性的例子來驗證我的這個觀點。

例一 對象方法調用

    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就是指向調用他或者是擁有他的對象

例二 構造函數創建

    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里面的其他方法就會報錯。

例三 改變this指向

  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的上下文,導致兩次結果不一致也是最好的證據。

最后

  本文最大的作用就是如果看完本文你能夠理解this為什么有時候會跟自己期望不一樣,而且能得到一個避免這樣問題發生的解決方案,那我的目的就達到了。很幸運你能看到這里,解決方案呈現給大家:就像Angular要將屬性和方法給你提供一個$scope來綁定屬性,也像coffeeScript會在對象一開頭有這么個賦值“ _this = this”,我們在自己的js實踐中不妨定義"val self = this",在之后的作用域里面用self來操作對象的屬性,這是解決之道。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM