2016-05-21 50 views
1

我無法理解'this'文字在打字稿中的工作方式。我無法訪問方法中的類成員。下面是我的代碼'此'範圍在打字稿回調函數中

class adopterDetailCtrl { 
    public adopter: IAdopter; 
    public $router: any; 

    static $inject = ['app.common.services.AdopterService']; 
    constructor(private adopterService: app.common.services.IAdopterServices) { 
     this.adopter = null; 
    } 

    $routerOnActivate(next) { 
     if (next.params.id > 0) { 
      this.getAdopterById(next.params.id); 
     } 
    } 

    getAdopterById(adopterId: number): void { 
     var AdopterList = this.adopterService.getAdopterById(); 
     AdopterList.query({ id: adopterId }, (data: adopter.IAdopter[]) => { 
      this.adopter = data[0];//this.adopter is undefined here. this refers to 'window' 
     }); 
    } 

    setAdopter(data: IAdopter) { 
     this.adopter = data;//can access this.adopter 
    } 
} 

回答

2

this上下文是在打字稿,因爲它是在JavaScript一樣,因爲你實際運行的代碼是編譯的JavaScript的編譯器打字稿輸出。

在javascript中,你有兩種方法來解決這個問題:

  1. 使用arrow function
  2. 使用Function.prototype.bind function

你可能會傳遞getAdopterById作爲回調,如果是那樣的話那麼使用bind將很容易解決:

let myobj = new adopterDetailCtrl(...); 

... 

someFunction(myobj.getAdopterById.bind(myobj)); 

還可以修改該實例中構造函數的方法中的參考:

(1)

class adopterDetailCtrl { 
    public adopter: IAdopter; 
    public $router: any; 

    static $inject = ['app.common.services.AdopterService']; 
    constructor(private adopterService: app.common.services.IAdopterServices) { 
     this.adopter = null; 

     this.getAdopterById = (adopterId: number) => { 
      var AdopterList = this.adopterService.getAdopterById(); 
      AdopterList.query({ id: adopterId }, (data: adopter.IAdopter[]) => { 
       this.adopter = data[0];//this.adopter is undefined here. this refers to 'window' 
      }); 
     } 
    } 

    $routerOnActivate(next) { 
     if (next.params.id > 0) { 
      this.getAdopterById(next.params.id); 
     } 
    } 

    getAdopterById: (adopterId: number) => void; 

    setAdopter(data: IAdopter) { 
     this.adopter = data;//can access this.adopter 
    } 
} 

注意,方法聲明爲空,執行使用在構造函數設定箭頭功能。

(2)

class adopterDetailCtrl { 
    public adopter: IAdopter; 
    public $router: any; 

    static $inject = ['app.common.services.AdopterService']; 
    constructor(private adopterService: app.common.services.IAdopterServices) { 
     this.adopter = null; 

     this.getAdopterById = this.getAdopterById.bind(this); 
    } 

    $routerOnActivate(next) { 
     if (next.params.id > 0) { 
      this.getAdopterById(next.params.id); 
     } 
    } 

    getAdopterById(adopterId: number): void { 
     var AdopterList = this.adopterService.getAdopterById(); 
     AdopterList.query({ id: adopterId }, (data: adopter.IAdopter[]) => { 
      this.adopter = data[0];//this.adopter is undefined here. this refers to 'window' 
     }); 
    } 

    setAdopter(data: IAdopter) { 
     this.adopter = data;//can access this.adopter 
    } 
} 

在這裏,在構造函數重新分配綁定this.getAdopterById.bind(this)this.getAdopterById

在這兩種情況下,您都可以自由傳遞getAdopterById方法作爲回調,而不用擔心this的範圍。

上的箭頭職能另一個需要注意的是,這是在ES6一個新的功能,如果你不選擇ES6目標在compilation options那麼編譯器實際上不會使用這個符號,而是將其轉換這樣的:

class A { 
    private x: number; 

    fn(): void { 
     setTimeout(() => console.log(this.x), 1); 
    } 
} 

要:

var A = (function() { 
    function A() { 
    } 
    A.prototype.fn = function() { 
     var _this = this; 
     setTimeout(function() { return console.log(_this.x); }, 1); 
    }; 
    return A; 
}()); 

這樣的this範圍被保存在_this,並在回調函數_this.x爲u sed而不是this.x