天天看點

TypeScript 函數中的 this 參數

從 TypeScript 2.0 開始,在函數和方法中我們可以聲明

this

的類型,實際使用起來也很簡單,比如:

function sayHello(this: void) {
  // this: void:表示在函數體内不允許使用this
}           

複制

在上面的 sayHello 函數中,

this

參數是僞參數,它位于函數參數清單的第一位。為什麼說

this

參數是僞參數呢?因為以上的 sayHello 函數經過編譯後,并不會生成實際的參數,該函數編譯成 ES5 後的代碼如下:

function sayHello() {
  // this: void:表示在函數體内不允許使用this
}           

複制

那麼在實際開發中,

this

參數有什麼用呢?下面我們來詳細介紹一下

this

參數的一些應用場景。

一、未使用 this 參數

class Rectangle {
  private w: number;
  private h: number;

  constructor(w: number, h: number) {
    this.w = w;
    this.h = h;
  }

  getArea() {
    return () => {
      return this.w * this.h;
    };
  }
}           

複制

以上代碼中,我們定義了一個

Rectangle

長方形類,該類中包含了兩個私有的 w 和 h 屬性,分别表示長方形的寬度和高度,此外還有一個

getArea

方法用于擷取長方形的面積。在

getArea

方法中我們沒有使用

this

參數,此時

this

的類型是 this,如下圖所示:

TypeScript 函數中的 this 參數

二、使用 this 參數

class Rectangle {
  private w: number;
  private h: number;

  constructor(w: number, h: number) {
    this.w = w;
    this.h = h;
  }

  getArea(this: Rectangle) {
    return () => {
      return this.w * this.h;
    };
  }
}           

複制

與前面定義的

Rectangle

長方形類不同,在

getArea

方法中,我們使用了

this

參數,之後

this

的類型是

Rectangle

類型,如下圖所示:

TypeScript 函數中的 this 參數

Rectangle

長方形類

getArea

方法中的

this

入參隻是作為一個形式上的參數,供 TypeScript 做靜态檢查時使用,編譯後并不會生成實際的入參。

三、禁止使用 this

有些時候,我們希望在方法中,禁止使用者使用

this

。針對這種需求,你可以設定 this 參數的類型為

void

class Rectangle {
  private w: number;
  private h: number;

  constructor(w: number, h: number) {
    this.w = w;
    this.h = h;
  }

  getArea(this: void) {
    return () => {
      return this.w * this.h;
    };
  }
}           

複制

以上代碼會提示以下異常:

Property 'w' does not exist on type 'void'.
Property 'h' does not exist on type 'void'.           

複制

四、回調函數中 this

前端開發者日常經常需要跟回調函數打交道,比如在頁面中監聽使用者的點選事件,然後執行對應的處理函數,具體示例如下:

const button = document.querySelector("button");
// ?. -> TS 3.7引入的可選鍊
button?.addEventListener("click", handleClick);

function handleClick() {
  console.log("Clicked!");
  // 'this' implicitly has type 'any' because it does not have a type annotation.
  this.removeEventListener("click", handleClick);
}           

複制

對于以上代碼,TypeScript 編譯器會有以下錯誤提示:

this

隐式具有

any

類型,這是因為它沒有類型注解。為了解決這個問題,我們就可以顯式指定

this

參數的類型:

const button = document.querySelector("button");
button?.addEventListener("click", handleClick);

function handleClick(this: HTMLElement) {
  console.log("Clicked!");
  this.removeEventListener("click", handleClick);
}           

複制

除此之外,TypeScript 2.0 還增加了一個新的編譯選項:

--noImplicitThis

,表示當 this 表達式值為 any 類型的時候,生成一個錯誤資訊。

五、參考資源

  • function-this-parameter
  • typescriptlang - typescript-2-0