【TS學習】(24)什么是裝飾器

在 TypeScript 中,裝飾器(Decorators) 是一種特殊的聲明,用于為類、類成員(屬性、方法、訪問器)、方法參數或整個類添加元數據或修改其行為。裝飾器是 JavaScript 和 TypeScript 的實驗性特性,廣泛應用于框架開發(如 Angular)和元編程場景。


1. 啟用裝飾器

在 TypeScript 中,默認情況下裝飾器是禁用的。要啟用裝飾器支持,需要在 tsconfig.json 文件中設置以下選項:

{"compilerOptions": {"experimentalDecorators": true}
}

2. 裝飾器的基本概念

(1) 定義
  • 裝飾器是一個函數,它接收一個目標對象作為參數,并可以對其進行修改或擴展。
  • 裝飾器通過 @ 符號應用到目標上。
(2) 語法
function Decorator(target: any): void {// 修改或擴展 target 的行為
}@Decorator
class MyClass {}

3. 類裝飾器

(1) 定義
  • 類裝飾器應用于類構造函數本身。
  • 它可以用來修改類的行為或添加元數據。
(2) 示例
function LogClass(constructor: Function) {console.log(`Class ${constructor.name} has been defined.`);
}@LogClass
class User {name: string;constructor(name: string) {this.name = name;}
}const user = new User("Alice"); // 輸出 "Class User has been defined."

在這里:

  • LogClass 是一個類裝飾器,用于記錄類的定義。

4. 方法裝飾器

(1) 定義
  • 方法裝飾器應用于類的方法。
  • 它可以用來修改方法的行為或添加元數據。
(2) 示例
function LogMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.log(`Calling method '${propertyKey}' with arguments: ${args}`);return originalMethod.apply(this, args);};
}class Calculator {@LogMethodadd(a: number, b: number): number {return a + b;}
}const calculator = new Calculator();
console.log(calculator.add(2, 3));
// 輸出:
// Calling method 'add' with arguments: 2,3
// 5

在這里:

  • LogMethod 是一個方法裝飾器,用于記錄方法調用及其參數。

5. 屬性裝飾器

(1) 定義
  • 屬性裝飾器應用于類的屬性。
  • 它可以用來添加元數據或修改屬性的行為。
(2) 示例
function LogProperty(target: any, propertyKey: string) {let value: any;const getter = function () {console.log(`Getting value of '${propertyKey}'`);return value;};const setter = function (newValue: any) {console.log(`Setting value of '${propertyKey}' to ${newValue}`);value = newValue;};Object.defineProperty(target, propertyKey, {get: getter,set: setter,enumerable: true,configurable: true,});
}class User {@LogPropertyname: string;constructor(name: string) {this.name = name;}
}const user = new User("Alice");
console.log(user.name); // 輸出 "Getting value of 'name'" 和 "Alice"
user.name = "Bob";      // 輸出 "Setting value of 'name' to Bob"

在這里:

  • LogProperty 是一個屬性裝飾器,用于記錄屬性的訪問和修改。

6. 參數裝飾器

(1) 定義
  • 參數裝飾器應用于方法的參數。
  • 它可以用來添加元數據或記錄參數信息。
(2) 示例
function LogParameter(target: any, propertyKey: string | symbol, parameterIndex: number) {console.log(`Parameter at index ${parameterIndex} in method '${String(propertyKey)}' is decorated.`);
}class Calculator {add(@LogParameter a: number, @LogParameter b: number): number {return a + b;}
}const calculator = new Calculator();
calculator.add(2, 3);
// 輸出:
// Parameter at index 0 in method 'add' is decorated.
// Parameter at index 1 in method 'add' is decorated.

在這里:

  • LogParameter 是一個參數裝飾器,用于記錄方法參數的索引和名稱。

7. 訪問器裝飾器

(1) 定義
  • 訪問器裝飾器應用于類的存取器(getter 和 setter)。
  • 它可以用來修改存取器的行為或添加元數據。
(2) 示例
function LogAccessor(target: any, propertyKey: string, descriptor: PropertyDescriptor) {const originalGetter = descriptor.get;const originalSetter = descriptor.set;descriptor.get = function () {console.log(`Getting value of '${propertyKey}'`);return originalGetter?.apply(this);};descriptor.set = function (value: any) {console.log(`Setting value of '${propertyKey}' to ${value}`);originalSetter?.apply(this, [value]);};
}class User {private _name: string;constructor(name: string) {this._name = name;}@LogAccessorget name(): string {return this._name;}set name(value: string) {this._name = value;}
}const user = new User("Alice");
console.log(user.name); // 輸出 "Getting value of 'name'" 和 "Alice"
user.name = "Bob";      // 輸出 "Setting value of 'name' to Bob"

在這里:

  • LogAccessor 是一個訪問器裝飾器,用于記錄存取器的訪問和修改。

8. 裝飾器工廠

裝飾器工廠是一個返回裝飾器函數的函數,允許傳遞參數以動態配置裝飾器。

示例
function Log(message: string) {return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.log(`${message}: Calling method '${propertyKey}' with arguments: ${args}`);return originalMethod.apply(this, args);};};
}class Calculator {@Log("Debug Info")add(a: number, b: number): number {return a + b;}
}const calculator = new Calculator();
calculator.add(2, 3);
// 輸出:
// Debug Info: Calling method 'add' with arguments: 2,3

在這里:

  • Log 是一個裝飾器工廠,允許傳遞自定義消息。

9. 實際應用場景

(1) 日志記錄
  • 使用裝飾器記錄方法調用、參數和返回值。
(2) 權限控制
  • 使用裝飾器檢查用戶權限,限制對某些方法的訪問。
示例
function RequireRole(role: string) {return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {if (role === "admin") {return originalMethod.apply(this, args);} else {throw new Error("Permission denied");}};};
}class AdminPanel {@RequireRole("admin")deleteUser(userId: number): void {console.log(`Deleting user with ID ${userId}`);}
}const panel = new AdminPanel();
panel.deleteUser(123); // 如果 role 不是 "admin",會拋出錯誤

10. 總結

特性描述
類裝飾器應用于類構造函數,用于修改類的行為或添加元數據。
方法裝飾器應用于類的方法,用于修改方法的行為或添加元數據。
屬性裝飾器應用于類的屬性,用于添加元數據或修改屬性的行為。
參數裝飾器應用于方法的參數,用于記錄參數信息或添加元數據。
訪問器裝飾器應用于存取器,用于修改存取器的行為或添加元數據。
裝飾器工廠返回裝飾器函數的函數,允許動態配置裝飾器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75278.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75278.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75278.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

datagrip如何連接數據庫

datagrip連接數據庫的步驟 2025版本 想要鏈接數據庫是需要一個jar包的,所以將上面進行刪除之后,需要下載一個jar包 那么這個時候需要鏈接上傳一個mysql鏈接的jar包 選擇核心驅動類 上述操作完成之后,然后點擊apply再點擊ok即可 如下圖說明my…

菊風RTC 2.0 開發者文檔正式發布,解鎖音視頻新體驗!

重磅發布! 開發者們,菊風實時音視頻2.0文檔已正式發布上線,為您提供更清晰、更高效的開發支持!讓菊風實時音視頻2.0為您的音視頻應用加速~ 菊風實時音視頻2.0聚焦性能升級、體驗升級、錄制服務升級,助力視頻通話、語…

輕量級碎片化筆記memos本地NAS部署與跨平臺跨網絡同步筆記實戰

文章目錄 前言1. 使用Docker部署memos2. 注冊賬號與簡單操作演示3. 安裝cpolar內網穿透4. 創建公網地址5. 創建固定公網地址 推薦 ? 前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。 點擊跳轉到網站 前言…

【Vue #2】腳手架 指令

一、腳手架 腳手架:一個保證各項工作順利開展的平臺,方便我們 拿來就用,零配置 1. Vue 代碼開發方式 相比直接 script 引入 vue 源碼,有沒有更好的方式編寫vue代碼呢? ① 傳統開發模式: 基于html文件開發Vue&…

ArkTS語言入門之接口、泛型、空安全、特殊運算符等

前言 臭寶們,今天我們來學習ArkTS中最后的一些內容。 實現接口 包含implements子句的類必須實現列出的接口中定義的所有方法,但使用默認實現定義的方法除外。 interface DateInterface {now(): string; } class MyDate implements DateInterface {no…

Maven超級詳細安裝部署

1.到底什么是Maven?搞清楚這個 Maven 是一個項目管理工具,主要用于 Java 項目的構建、依賴管理和文檔生成。 它基于項目對象模型(POM),通過 pom.xml 文件定義項目的配置。 (簡單說破:就是工程…

高并發內存池(三):PageCache(頁緩存)的實現

前言: 在前兩期內容中,我們深入探討了內存管理機制中在 ThreadCache 和 CentralCache兩個層級進行內存申請的具體實現。這兩層緩存作為高效的內存分配策略,能夠快速響應線程的內存需求,減少鎖競爭,提升程序性能。 本期…

機器學習 | 強化學習方法分類匯總 | 概念向

文章目錄 ??Model-Free RL vs Model-Based RL??核心定義??核心區別??Policy-Based RL vs Value-Based RL??核心定義?? 核心區別??Monte-Carlo update vs Temporal-Difference update??核心定義??核心區別??On-Policy vs Off-Policy??核心定義??核心區別…

GSO-YOLO:基于全局穩定性優化的建筑工地目標檢測算法解析

論文地址:https://arxiv.org/pdf/2407.00906 1. 論文概述 《GSO-YOLO: Global Stability Optimization YOLO for Construction Site Detection》提出了一種針對建筑工地復雜場景優化的目標檢測模型。通過融合全局優化模塊(GOM)?、穩定捕捉模塊(SCM)?和創新的AIoU損失函…

Java學習手冊:JVM、JRE和JDK的關系

在Java生態系統中,JVM(Java虛擬機)、JRE(Java運行時環境)和JDK(Java開發工具包)是三個核心概念。它們共同構成了Java語言運行和開發的基礎。理解它們之間的關系對于Java開發者來說至關重要。本文…

lanqiaoOJ 2489 進制

//x的初始值一定要設置為0,否則測試的答案是對的,但是通不過去 #include<bits/stdc.h> using namespace std; const int N50; int a[N]; using lllong long; int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); string s"2021ABCD"; for(int i…

Python基礎知識點(類和對象)

""" 編程思維---解決問題的方式方法 面向過程---C語言 面向對象---C java python python中封裝類的語法 class 類名&#xff08;父類&#xff09; 類體 注意&#xff1a; 1.類名--約定 大駝峰法 首字母要大寫 2.父類如果有的話就寫&#xff0c;沒有的話…

記錄一下學習docker的命令(不斷補充中)

#2025-04-10,22:12############### 在wsl2中安裝了ubuntu24.04.1后有部署了docker&#xff0c; 如果沒有啟動docker可以通過下列命令啟動docker&#xff1a; sudo systemctl start docker 執行下列命令可以看到docker狀態&#xff0c;并不占用控制臺的命令&#xff1a; su…

【01BFS】# P4667 [BalticOI 2011] Switch the Lamp On 電路維修 (Day1)|普及+

本文涉及知識點 CBFS算法 題目描述 Casper is designing an electronic circuit on a N M N \times M NM rectangular grid plate. There are N M N \times M NM square tiles that are aligned to the grid on the plate. Two (out of four) opposite corners of each …

參考平面跨分割情況下的信號回流

前言&#xff1a;弄清楚信號的回流路徑&#xff0c;是學習EMC和高速的第一步&#xff01; 如果我們不管信號的回流路徑&#xff0c;會造成什么后果&#xff1f;1、信號完整性問題&#xff0c;信號的回流路徑不連續會導致信號反射、衰減和失真。2、信號衰減和噪聲干擾&#xff…

almalinux 8 9 升級到指定版本

almalinux 8 update 指定版本 almalinux歷史版 所有版本almalinux最新版 所有版本vault歷史版 almalinux最新版 (https://repo.almalinux.org )地址后面增加不同名稱 echo "delete repos" rm -rf /etc/yum.repos.d/*echo "new almalinux repo" cat <&…

阿里云CDN應對DDoS攻擊策略

阿里云CDN遭遇DDoS攻擊時&#xff0c;可通過以下綜合措施進行應對&#xff0c;保障服務的穩定性和可用性&#xff1a; 1. 啟用阿里云DDoS防護服務 阿里云提供專業的DDoS防護服務&#xff0c;通過流量清洗中心過濾惡意流量&#xff0c;確保合法請求正常傳輸。該服務支持按需選…

CentOS Stream release 9安裝 MySQL(一)

在 CentOS Stream 上安裝 MySQL 的方法與傳統的 CentOS 類似&#xff0c;但由于 CentOS Stream 的軟件包更新策略不同&#xff0c;可能會遇到一些依賴問題。以下是詳細安裝步驟&#xff1a; 1. 添加 MySQL 官方 Yum 倉庫 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-co…

數據結構 | 證明鏈表環結構是否存在

?個人主頁&#xff1a; 鏈表環結構 0.前言1.環形鏈表&#xff08;基礎&#xff09;2.環形鏈表Ⅱ&#xff08;中等&#xff09;3.證明相遇條件及結論3.1 問題1特殊情況證明3.2 問題1普適性證明 0.前言 在這篇博客中&#xff0c;我們將深入探討鏈表環結構的檢測方法&#xff1a;…

數字世界的免疫系統:惡意流量檢測如何守護網絡安全

在2023年全球網絡安全威脅報告中,某跨國電商平臺每秒攔截的惡意請求峰值達到217萬次,這個數字背后是無數黑客精心設計的自動化攻擊腳本。惡意流量如同數字世界的埃博拉病毒,正在以指數級速度進化,傳統安全防線頻頻失守。這場沒有硝煙的戰爭中,惡意流量檢測技術已成為守護網…