欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談JS裝飾器以及裝飾器在TS中的使用方式

 更新時間:2023年07月16日 09:30:01   作者:菜雞夯師傅  
這篇文章主要帶大家探討一下JS裝飾器以及裝飾器在TS中的使用方式,文中有詳細的代碼示例,對裝飾器不太了解的同學可以參考閱讀本文學習了一下

類裝飾器

什么是類裝飾器呢?

類裝飾器的本質(zhì)是一個函數(shù),該函數(shù)接受一個參數(shù),表示類本身(構造函數(shù)本身)。 那么類裝飾器該如何使用呢?

    function decorator (target) {
    }
    @decorator
    class A {
    }

這樣的話就完成了類裝飾器的編寫。不難看出類裝飾器的調(diào)用方式就是@函數(shù)名的方式放在一個類的聲明之前。那如果在TS中使用的話,我們都知道TS中有類型檢查,那對于裝飾器而言,主要在形參的類型上需要我們自己定義。那類裝飾器的形參表示的是類本身,該如何定義呢?

我們知道JS中的類其實就是一個函數(shù),所以我們可以使用Function來對類進行類型定義。但是這不是很嚴謹,因為類是可以用new關鍵字來聲明的,并且會返回一個object,所以更推薦使用new (參數(shù)) => object來定義類的類型。那么以上代碼就會被改造成這樣:

    type decoratorType = new (...args:any[]) => object;
    function decorator ( target : decorarorType ) {
    };
    @decorator;
    class A {
    }

值得注意的是,ts可能會在類名處有錯誤提示,這是因為裝飾器在ts中還處于試驗階段。我們可以在 tsconfig.json中配置experimentalDecoratorstrue來規(guī)避這個報錯。

類裝飾器的運行時機

類裝飾器的運行時間是在類定義后直接運行。我們可以驗證一下:

運行后發(fā)現(xiàn),在class A定義完成后立即就輸出了我是decorator。

從編譯結果上也能很容易的看出,裝飾器是在類定義后直接調(diào)用的:

  // 這里有一個函數(shù) 他的第一個參數(shù)decorators表示裝飾器數(shù)組,第二個參數(shù)target表示被裝飾的類本身。
  var __decorate =
  (this && this.__decorate) ||
  function (decorators, target, key, desc) {
    var c = arguments.length,
      r =
        c < 3
          ? target
          : desc === null
          ? (desc = Object.getOwnPropertyDescriptor(target, key))
          : desc,
      d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
     // 調(diào)用裝飾器
      r = Reflect.decorate(decorators, target, key, desc);
    else
      for (var i = decorators.length - 1; i >= 0; i--)
       // 調(diào)用裝飾器(從后往前)
        if ((d = decorators[i]))
          r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
// 這時我們定義的裝飾器函數(shù)
function decotator(target) {
  console.log("我是decorator");
}
// 定義類
let A = class A {};
// 裝飾器和類作為參數(shù)傳入__decorate中運行。
A = __decorate([decotator], A);

裝飾器的返回值

裝飾器可以有以下幾種返回值:

  • void
  • 一個新的類:會將新的類替換掉裝飾目標

這里具體演示第二種返回值----返回一個新的類。在裝飾器中返回新的類class B。此時new一個class A的實例,打印后發(fā)現(xiàn)為class B的實例對象。說明class A通過裝飾器已經(jīng)被替換為class B了。

所以說在裝飾器中可以通過以上方式,增強被裝飾類的功能。不過在ts中這種方式可能丟失一些類型檢查。如下圖:

這是因為裝飾器是一個通用的,雖然在當前場景下因為class B繼承了裝飾器傳入的class A,因為類裝飾器的入?yún)⑹?strong>動態(tài)的,所以ts并不能知道到底有沒有prop1這個屬性。當然這樣并不會影響代碼的功能,只是在ts中會丟失類型檢查。

那么如果我想讓裝飾器能夠接受一些額外的內(nèi)容,該怎么做呢?在實際開發(fā)中,可能需要某些數(shù)據(jù)來參與邏輯。那么我們可以用以下方式來實現(xiàn):

type decoratorType = new (...args: any) => object;
function decorator(str: string) {
  return function (target: decoratorType) {
    console.log(str);
    console.log(target);
  };
}
@decorator("這是一個類")
class A {}

因為需要接受額外的信息,所以這必然是需要一個函數(shù)調(diào)用的形式。這里 @decorator接受了一個字符串參數(shù)。并且decorator函數(shù)接受一個形參str且返回一個新的函數(shù),所以decorator函數(shù)返回的函數(shù)會作為真正的裝飾器,它可以接收到被修飾類class A。我們可以看一下運行結果。

多個裝飾器的情況

那么如果有多個裝飾器呢?他們的運行順序是我們想的那樣從上到下依次運行的嗎?比如有以下代碼:

type decoratorType = new (...args: any) => object;
function decorator1(target: decoratorType) {
  console.log("我是裝飾器1");
}
function decorator2(target: decoratorType) {
  console.log("我是裝飾器2");
}
function decorator3(target: decoratorType) {
  console.log("我是裝飾器3");
}
@decorator1
@decorator2
@decorator3
class A {}

按照我們一貫的思維,因為是同步代碼,所以會按順序執(zhí)行,事實真的是這樣嗎?讓我們來看一下運行結果:

不難發(fā)現(xiàn)裝飾器的運行順序是遵循后加入先調(diào)用的形式!從編譯結果也能發(fā)現(xiàn):

var __decorate =
  (this && this.__decorate) ||
  function (decorators, target, key, desc) {
    var c = arguments.length,
      r =
        c < 3
          ? target
          : desc === null
          ? (desc = Object.getOwnPropertyDescriptor(target, key))
          : desc,
      d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
     // 調(diào)用裝飾器
      r = Reflect.decorate(decorators, target, key, desc);
    else
      for (var i = decorators.length - 1; i >= 0; i--)
       //看這里 調(diào)用裝飾器(從后往前因為是i--且i的初始值是裝飾器數(shù)組的實際長度)
        if ((d = decorators[i]))
          r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
  };

那如果把裝飾器作為一個函數(shù)來調(diào)用呢?

type decoratorType = new (...args: any) => object;
function decorator1(str: string) {
  console.log("第一個函數(shù)運行了");
  return function (target: decoratorType) {
    console.log(str);
  };
}
function decorator2(str: string) {
  console.log("第二個函數(shù)運行了");
  return function (target: decoratorType) {
    console.log(str);
  };
}
function decorator3(str: string) {
  console.log("第三個函數(shù)運行了");
  return function (target: decoratorType) {
    console.log(str);
  };
}
@decorator1("我是裝飾器1")
@decorator2("我是裝飾器2")
@decorator3("我是裝飾器3")
class A {}

當作為函數(shù)調(diào)用時,會先執(zhí)行函數(shù)體,因為該函數(shù)又返回了一個函數(shù),所以返回的新函數(shù)會作為裝飾器。運行第一個函數(shù)會的到第一個裝飾器,以此類推會獲得三個裝飾器。而裝飾器是按照后加入先調(diào)用的形式,所以會輸出以下結果:

從編譯結果來看能更好的理解:

function decorator1(str) {
  console.log("第一個函數(shù)運行了");
  return function (target) {
    console.log(str);
  };
}
function decorator2(str) {
  console.log("第二個函數(shù)運行了");
  return function (target) {
    console.log(str);
  };
}
function decorator3(str) {
  console.log("第三個函數(shù)運行了");
  return function (target) {
    console.log(str);
  };
}
let A = class A {};
A = __decorate(
  [
    decorator1("我是裝飾器1"), // 第一個函數(shù)的返回結果作為裝飾器
    decorator2("我是裝飾器2"), // 第二個函數(shù)的返回結果作為裝飾器
    decorator3("我是裝飾器3"), // 第三個函數(shù)的返回結果作為裝飾器
  ],
  A
);

結尾

如果讀完這篇文章能夠幫助你更好的理解類裝飾器,歡迎留言討論、點贊收藏。

以上就是淺談JS裝飾器以及裝飾器在TS中的使用方式的詳細內(nèi)容,更多關于JS裝飾器使用方法的資料請關注腳本之家其它相關文章!

相關文章

  • JS獲取時間的相關函數(shù)及時間戳與時間日期之間的轉(zhuǎn)換

    JS獲取時間的相關函數(shù)及時間戳與時間日期之間的轉(zhuǎn)換

    時間戳和時間日期的轉(zhuǎn)換是常見的操作,下面就通過代碼實例介紹一下如何實現(xiàn)它們之間的相互轉(zhuǎn)換,感興趣的朋友一起學習吧
    2016-02-02
  • JavaScript實現(xiàn)計數(shù)器基礎方法

    JavaScript實現(xiàn)計數(shù)器基礎方法

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)計數(shù)器的基礎方法
    ,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • javascript 處理事件綁定的一些兼容寫法

    javascript 處理事件綁定的一些兼容寫法

    javascript 事件綁定的一些兼容寫法整理非常不錯,感謝
    2009-12-12
  • js圖片輪播特效代碼分享

    js圖片輪播特效代碼分享

    這篇文章主要介紹了js圖片輪播特效,圖片切換效果特別適合做產(chǎn)品演示,感興趣的小伙伴可以參考下
    2015-09-09
  • JS實現(xiàn)代碼雨特效

    JS實現(xiàn)代碼雨特效

    這篇文章主要為大家詳細介紹了JS實現(xiàn)代碼雨特效,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • JavaScript中的字符串操作詳解

    JavaScript中的字符串操作詳解

    這篇文章介紹了JavaScript中的字符串操作,有需要的朋友可以參考一下
    2013-11-11
  • javascript導出csv文件(excel)的方法示例

    javascript導出csv文件(excel)的方法示例

    這篇文章主要給大家介紹了關于javascript導出csv文件(excel)的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用javascript具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-08-08
  • 詳解js location.href和window.open的幾種用法和區(qū)別

    詳解js location.href和window.open的幾種用法和區(qū)別

    這篇文章主要介紹了詳解js location.href和window.open的幾種用法和區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • bootstrap手風琴制作方法詳解

    bootstrap手風琴制作方法詳解

    這篇文章主要為大家詳細介紹了bootstrap手風琴的制作方法,制作聲明式觸發(fā)手風琴,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 前端常用的js函數(shù)方法

    前端常用的js函數(shù)方法

    這篇文章主要給大家分享的是常用的js函數(shù)的方法,告別搜索引擎的幫助,提高你的開發(fā)效率,,需要的朋友可以參考一下,希望對你的學習有所幫助
    2021-12-12

最新評論