日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

代码缺乏装饰?使用ts装饰器来装饰你的代码

發布時間:2023/12/4 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 代码缺乏装饰?使用ts装饰器来装饰你的代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

TypeScript中的裝飾器

  • 👏序言
  • 😉一、類的裝飾器
    • 1、什么是裝飾器
    • 2、裝飾器的特點
    • 3、幾種類的裝飾器
      • (1)執行順序
      • (2)參數判斷
      • (3)裝飾器標準寫法
  • 🤐二、類的其他裝飾器
    • 1、方法裝飾器
    • 2、訪問器的裝飾器
    • 3、屬性的裝飾器
    • 4、參數裝飾器
  • 😐三、裝飾器實際使用的小例子
  • 😏四、結束語
  • 🥳 往期推薦

👏序言

在 ts 中,有一個經常被我們熟用但是又很少去注意的一個知識點,裝飾器。那在下文中,將講解類的裝飾器,一起類裝飾器中的幾種其他的裝飾器。

下面開始本文的講解~😜

😉一、類的裝飾器

1、什么是裝飾器

首先,我們先來講, TypeScript 中,類的裝飾器是什么。

裝飾器實際上是一種對類的修飾工具。比如說:某一天可能有個女孩子想要出去逛街,那么她可能會畫個美美的妝出門。因此,我們可以把裝飾器視為是化妝的這個過程,也就是一個美化的過程。

現在就是,假設我們有一個類,然后呢,要對它額外進行一些修飾,這個就是裝飾器要干的事情了。

2、裝飾器的特點

首先我們需要先來了解裝飾器的幾個特點。具體如下:

  • 裝飾器本身就是一個函數
  • 裝飾器接收的參數是構造函數
  • 裝飾器通過 @ 符號來進行使用。

依據以上這幾個特點,下面我們來了解幾種類的裝飾器。

3、幾種類的裝飾器

(1)執行順序

// 第一個裝飾器 function testDecorator(constructor: any) {console.log('decorator'); }// 第二個裝飾器 function testDecorator1(constructor: any) {console.log('decorator1'); }// 裝飾器執行的時候,是從下到上,從右到左的順序 @testDecorator @testDecorator1 class Test {}const test = new Test(); // decorator1 decorator

裝飾器執行的時候,是從下到上,從右到左的順序。

(2)參數判斷

我們如何讓類裝飾器接收一個參數呢?來看一段代碼:

// 外面再包一層函數 function testDecorator(flag: boolean) {// 工廠模式if (flag) {return function (constructor: any) {constructor.prototype.getName = () => {console.log('Monday');};};} else {return function (constructor: any) {};} }@testDecorator(true) class Test {}const test = new Test(); (test as any).getName(); // Monday

通過上面這段代碼我們可以了解到,我們通過對類裝飾器的外部再包上一層函數,這其實有點像柯里化的形式,之后通過外部的這個函數進行傳參,也就是上面代碼中的 flag 。最終類裝飾器返回一個函數作為結果,順利地進行傳參。

(3)裝飾器標準寫法

上面的兩個裝飾器屬于兩個比較簡單和不太規范的裝飾器。下面我們來展現一種比較標準的寫法:

function testDecorator() {return function <T extends new (...args: any[]) => any>(constructor: T) {return class extends constructor {name = 'Tuesday';getName() {return this.name;}};}; }const Test = testDecorator()(class {name: string;constructor(name: string) {this.name = name;}} );const test = new Test('Monday'); console.log(test.getName()); // Tuesday

在上面的代碼中, (...args: any[]) => any 是一個函數,返回值是一個對象的類型。這個函數會接收很多參數,函數把這些參數合并到一起,變成一個數組,也就是 ...args 。那 <T extends new (...args: any[]) => any> 是什么意思呢?意思是, T 可以通過 new (...args: any[]) => any 這種類型的構造函數,給實例化出來。所以 T 現在可以理解為是一個類或者是 constructor 這樣的一個構造函數。

最終,我們通過 testDecorator()() 這樣的方式,讓 test 實例可以訪問到 getName() 方法,并打印出 Tuesday 。

🤐二、類的其他裝飾器

1、方法裝飾器

這里我想要強調的一個問題是,大家覺得,類裝飾器的執行時刻是什么樣的?類裝飾器在類定義完成之后就可以立即對進行一個裝飾。

那方法裝飾器,是什么樣的呢?

方法裝飾器,跟類裝飾器也是一樣的。它會等類創建好了之后,立即地把方法去做一個修改。

很多小伙伴可能會誤認為,我是不是得實例化的時候,才會對方法去做一個裝飾呢?其實不是這樣的,只要在定義完以后,就會幫助我們對類的方法去做一個裝飾。先來看一段代碼:

// 普通方法, target 對應的是類的 prototype // 靜態方法, target 對應的是類的 構造函數 function getNameDecorator(target: any,key: string,descriptor: PropertyDescriptor ) {// console.log(target);// descriptor的作用:對方法中的屬性做一些編輯descriptor.writable = true;// 通過調用 .value 的方式,可以對原來的方法做一些變更descriptor.value = function () {return 'decorator';}; }class Test {name: string;constructor(name: string) {this.name = name;}@getNameDecoratorgetName() {return this.name;} }const test = new Test('Monday'); test.getName = () => {return '123'; }; console.log(test.getName()); // decorator

大家先看上面這段代碼,可能有的小伙伴會覺得,最終打印的是 123 。但其實,因為我們對方法進行了裝飾,所以最終打印的結果是 decorator 。

因此,一個裝飾器對一個方法做完裝飾之后,就可以多做很多事情了。包括原型target,key值 和 descriptor ,都可以對方法做很多修改。

2、訪問器的裝飾器

現在,我們來學習類里面中,訪問器的裝飾器。我們先來看一段代碼:

function visitDecorator(target: any,key: string,descriptor: PropertyDescriptor ) {// console.log(123); }class Test {private _name: string;constructor(name: string) {this._name = name;}// 這里不能寫@visitDecorator,同時寫兩個會引發報錯get name() {return this._name;}@visitDecoratorset name(name: string) {this._name = name;} }const test = new Test('Monday'); test.name = 'Tuesday'; console.log(test.name); // Tuesday

其中, @visitDecorator 是一個訪問器裝飾器。我們現在來解釋下上面代碼中的運行路徑。

第一部分, test.name = 'Tuesday' 走的是 set 方法,把 Tuesday 這個值賦值給 name 。之后,等到我們運行 console.log 的時候,就是去調用 get 方法,所以最終打印出來的也就是 Tuesday 而不是 Monday 。

3、屬性的裝飾器

我們先來看第一種屬性的裝飾器。具體代碼如下:

function nameDecorator(target: any, key: string): any {const descriptor: PropertyDescriptor = {writable: true,};return descriptor; }class Test {@nameDecoratorname = 'Monday'; }const test = new Test(); test.name = 'Tuesday'; console.log(test.name); // Tuesday

屬性裝飾器的寫法,也是一個 decorator 的形式,即上述代碼中的 @nameDecorator 。這個裝飾器接收兩個參數,分別是 原型target屬性的名字key 。在這里我們可以返回一個 descriptor 來替換掉屬性原始的 descriptor 。替換完成之后,最終打印 Tuesday 。


繼續,我們來看第二種裝飾器。具體代碼如下:

// 該裝飾器無法直接修改實例上的屬性值(name),而只能修改原型上的屬性值(name) function nameDecorator(target: any, key: string): any {target[key] = 'Tuesday'; }// name存儲在類的實例上 class Test {@nameDecoratorname = 'Monday'; }const test = new Test(); test.name = 'Hello~'; console.log((test as any).name); // Hello~ console.log((test as any).__proto__.name); // Tuesday

這種類型的裝飾器中,值得注意的點是, nameDecorator 只能用來修改原型上的屬性值,而無法直接修改實例上的屬性值。

4、參數裝飾器

上面我們講到了對類里面的方法、訪問器和屬性做修飾,現在,我們再來了解一種新的裝飾器:對類里面的方法中的參數做修飾。先來看一段代碼:

// 原型,方法名,參數所在的位置 function paramDecorator(target: any, key: string, paramIndex: number): any {console.log(target, key, paramIndex); // Test { getInfo: [Function] } , 'getInfo' , 1(參數所在位置是第2個位置) }class Test {getInfo(name: string, @paramDecorator age: number) {console.log(name, age);} }const test = new Test(); test.getInfo('Monday', 18); // Monday 18

大家可以看到,通過對方法中的參數進行裝飾,我們可以獲取到裝飾器的原型方法名參數所在的位置,這個就是參數裝飾器。

😐三、裝飾器實際使用的小例子

上面我們講到了很多種裝飾器相關的原理知識,現在我們用一個實際使用的例子來帶大家更好的使用裝飾器。先看一段代碼:

const userInfo: any = undefined;function catchError(msg: string) {return function (target: any, key: string, descriptor: PropertyDescriptor) {const fn = descriptor.value;descriptor.value = function () {try {fn();} catch (e) {console.log(msg);}};}; }class Test {@catchError('userInfo.name 不存在')getName() {return userInfo.name;}@catchError('userInfo.age 不存在')getAge() {return userInfo.age;}@catchError('userInfo.gender 不存在')getGender() {return userInfo.gender;} }const test = new Test(); test.getName(); // userInfo.name 不存在 test.getAge(); // userInfo.age 不存在 test.getGender(); // userInfo.gender 不存在

在上面的代碼中,我們做的是捕獲異常的一個功能。通過封裝 @catchError 裝飾器,來對我們最終使用的三個方法,getName 、 getAge 和 getGender ,對這三個方法進行異常捕獲

以上算是對裝飾器的一次小小的實踐,后續深入學習可以再參考一些書籍去多練習。

😏四、結束語

在上面的文章中,我們講解了裝飾器中最基礎的類裝飾器,以及類裝飾器中的4中其他類型的裝飾器。最后,我們還用了一個小例子去簡單地了解了,裝飾器在實際應用中的一些操作。

到這里,關于裝飾器的學習就接近尾聲啦!不知道小伙伴們對裝飾器又有了一些新的了解呢?

如果您覺得這篇文章有幫助到您的的話不妨點贊支持一下喲~~😉

我們下期再見!👋👋👋

🥳 往期推薦

🛵TypeScript,從0到入門帶你進入類型的世界

總結

以上是生活随笔為你收集整理的代码缺乏装饰?使用ts装饰器来装饰你的代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。