- TypeScript 基礎
- TypeScript - 首頁
- TypeScript - 路線圖
- TypeScript - 概述
- TypeScript - 環境搭建
- TypeScript - 基本語法
- TypeScript vs. JavaScript
- TypeScript - 特性
- TypeScript - 變數
- TypeScript - let & const
- TypeScript - 運算子
- TypeScript 基本型別
- TypeScript - 型別
- TypeScript - 型別註解
- TypeScript - 型別推斷
- TypeScript - 數字
- TypeScript - 字串
- TypeScript - 布林值
- TypeScript - 陣列
- TypeScript - 元組
- TypeScript - 列舉
- TypeScript - Any
- TypeScript - Never
- TypeScript - 聯合型別
- TypeScript - 字面量型別
- TypeScript - 符號
- TypeScript - null vs. undefined
- TypeScript - 類型別名
- TypeScript 控制流
- TypeScript - 決策語句
- TypeScript - If 語句
- TypeScript - If Else 語句
- TypeScript - 巢狀 If 語句
- TypeScript - Switch 語句
- TypeScript - 迴圈
- TypeScript - For 迴圈
- TypeScript - While 迴圈
- TypeScript - Do While 迴圈
- TypeScript 函式
- TypeScript - 函式
- TypeScript - 函式型別
- TypeScript - 可選引數
- TypeScript - 預設引數
- TypeScript - 匿名函式
- TypeScript - 函式構造器
- TypeScript - Rest 引數
- TypeScript - 引數解構
- TypeScript - 箭頭函式
- TypeScript 介面
- TypeScript - 介面
- TypeScript - 擴充套件介面
- TypeScript 類和物件
- TypeScript - 類
- TypeScript - 物件
- TypeScript - 訪問修飾符
- TypeScript - 只讀屬性
- TypeScript - 繼承
- TypeScript - 靜態方法和屬性
- TypeScript - 抽象類
- TypeScript - 訪問器
- TypeScript - 鴨子型別
- TypeScript 高階型別
- TypeScript - 交叉型別
- TypeScript - 型別守衛
- TypeScript - 型別斷言
- TypeScript 型別操作
- TypeScript - 從型別建立型別
- TypeScript - Keyof 型別運算子
- TypeScript - Typeof 型別運算子
- TypeScript - 索引訪問型別
- TypeScript - 條件型別
- TypeScript - 對映型別
- TypeScript - 模板字面量型別
- TypeScript 泛型
- TypeScript - 泛型
- TypeScript - 泛型約束
- TypeScript - 泛型介面
- TypeScript - 泛型類
- TypeScript 雜項
- TypeScript - 三斜槓指令
- TypeScript - 名稱空間
- TypeScript - 模組
- TypeScript - 環境宣告
- TypeScript - 裝飾器
- TypeScript - 型別相容性
- TypeScript - Date 物件
- TypeScript - 迭代器和生成器
- TypeScript - Mixins
- TypeScript - 實用程式型別
- TypeScript - 裝箱和拆箱
- TypeScript - tsconfig.json
- 從 JavaScript 到 TypeScript
- TypeScript 有用資源
- TypeScript - 快速指南
- TypeScript - 有用資源
- TypeScript - 討論
TypeScript - 裝飾器
TypeScript 中的裝飾器是一種特殊的宣告,可以附加到類宣告、屬性、訪問器、方法和引數上。它用於在不修改原始原始碼的情況下單獨修改類。這使得它們成為面向物件程式設計領域中強大的工具,允許您編寫更簡潔、更有條理的程式碼,並遵循 DRY(不要重複自己)原則。
在 TypeScript 中使用裝飾器
您需要啟用“experimentalDecorators”編譯器選項以啟用 TypeScript 專案中對裝飾器的實驗性支援。
有兩種方法可以在 TypeScript 中啟用“experimentalDecorators”編譯器選項。您可以使用任何一個選項。
- 在專案目錄的終端中執行以下命令。tsc --target ES5 --experimentalDecorators
- 或者,您可以更新tsconfig.js檔案並在 compilerOptions 物件中新增"experimentalDecorators": true 屬性。
{ "compilerOptions": { "target": "ES5", "experimentalDecorators": true } }
裝飾器語法
您可以按照以下語法在 TypeScript 中使用裝飾器。
@DecoratorName
在上述語法中,“DecoratorName”是帶有“@”符號字首的函式名。表示式必須在執行時計算“DecorateName”函式。
裝飾器工廠
每當您需要自定義裝飾器函式如何應用於宣告時,它們可以使用裝飾器工廠。裝飾器工廠函式返回將在執行時計算的表示式。
請按照以下語法使用裝飾器工廠函式。
function decoratorName(args: string) {
// Decorator factory returns the function expression
return function (target) {
// This is the decorator which will be evaluated at the run time.
};
}
在上述語法中,“args”是傳遞給裝飾器函式的引數,“target”是類的原型。
裝飾器組合
您可以將多個裝飾器與特定宣告一起使用。多個裝飾器可以單行使用或多行使用,如下所示。
單行
@f @g x
或者,多行
@f @g x
在上述語法中,“f”和“g”裝飾器與單個宣告“x”一起使用。
為什麼要使用裝飾器?
讓我們舉一個簡單的例子來了解裝飾器的用例。
// Defining a class
class Student {
// Declaring the properties of the class
constructor(private name: string, private rollNo: number) { }
// Defining the methods of the class
sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
printrollNo() {
console.log(`My RollNo is ${this.rollNo}.`);
}
}
// Creating an object of the class
const user = new Student("John", 20);
// Accessing the properties of the class
user.sayHello();
user.printrollNo();
編譯後,它將生成以下 JavaScript 程式碼
// Defining a class
class Student {
// Declaring the properties of the class
constructor(name, rollNo) {
this.name = name;
this.rollNo = rollNo;
}
// Defining the methods of the class
sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
printrollNo() {
console.log(`My RollNo is ${this.rollNo}.`);
}
}
// Creating an object of the class
const user = new Student("John", 20);
// Accessing the properties of the class
user.sayHello();
user.printrollNo();
它產生以下輸出
Hello, my name is John. My RollNo is 20.
現在,如果我們希望在函式執行開始和結束時記錄該函式,該怎麼辦?我們需要在每個函式的開頭和結尾新增日誌,如下面的程式碼所示。
// Defining a class
class Student {
// Declaring the properties of the class
constructor(private name: string, private rollNo: number) { }
// Defining the methods of the class
sayHello() {
console.log("Start: sayHello");
console.log(`Hello, my name is ${this.name}.`);
console.log("End: sayHello");
}
printrollNo() {
console.log("Start: printrollNo");
console.log(`My RollNo is ${this.rollNo}.`);
console.log("End: printrollNo");
}
}
// Creating an object of the class
const user = new Student("John", 20);
// Accessing the properties of the class
user.sayHello();
user.printrollNo();
編譯後,它將生成以下 JavaScript 程式碼
// Defining a class
class Student {
// Declaring the properties of the class
constructor(name, rollNo) {
this.name = name;
this.rollNo = rollNo;
}
// Defining the methods of the class
sayHello() {
console.log("Start: sayHello");
console.log(`Hello, my name is ${this.name}.`);
console.log("End: sayHello");
}
printrollNo() {
console.log("Start: printrollNo");
console.log(`My RollNo is ${this.rollNo}.`);
console.log("End: printrollNo");
}
}
// Creating an object of the class
const user = new Student("John", 20);
// Accessing the properties of the class
user.sayHello();
user.printrollNo();
它將產生以下輸出
Start: sayHello Hello, my name is John. End: sayHello Start: printrollNo My RollNo is 20. End: printrollNo
如果我們想重用記錄函式執行的邏輯而不編寫重複的程式碼,該怎麼辦?在這裡,裝飾器就派上用場了。
讓我們透過下面的例子來學習它。
// Decorator factory
function printExecution(method: any, _context: any) {
// Returning a new function
return function (value: any, ...args: any[]) {
// Logging the method name at the start
console.log("start:", method.name);
// Calling the original method
const result = method.call(value, ...args);
// Logging the method name at the end
console.log("end:", method.name);
return result;
}
}
// Defining a class
class Student {
// Declaring the properties of the class
constructor(private name: string, private rollNo: number) { }
// Defining the methods of the class
@printExecution
sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
@printExecution
printrollNo() {
console.log(`My RollNo is ${this.rollNo}.`);
}
}
// Creating an object of the class
const user = new Student("John", 20);
// Accessing the properties of the class
user.sayHello();
user.printrollNo();
以上程式碼列印與之前程式碼相同的輸出。
Start: sayHello Hello, my name is John. End: sayHello Start: printrollNo My RollNo is 20. End: printrollNo
類裝飾器
類裝飾器與類宣告一起使用,以觀察或修改類定義。
示例
// Decorator factory
function LogClass(target: Function) {
console.log(`${target.name} is instantiated`);
}
// Decorator
@LogClass
class MyClass {
constructor() { console.log("MyClass instance created"); }
}
// Create an instance of the class
const myClassInstance = new MyClass();
編譯後,它將生成以下 JavaScript 程式碼
// Class definition
class MyClass {
constructor() { console.log("MyClass instance created"); }
}
// Decorator
LogClass(MyClass);
// Create an instance of the class
const myClassInstance = new MyClass();
輸出
MyClass instance created MyClass is instantiated
方法裝飾器
方法裝飾器用於替換、修改或觀察方法定義。它與方法定義一起使用。
示例
// Decorator factory
function printExecution(method: any, _context: any) {
// Returning a new function
return function (value: any, ...args: any[]) {
// Logging the method name at the start
console.log("start:", method.name);
// Calling the original method
const result = method.call(value, ...args);
return result;
}
}
// Defining a class
class Person {
constructor(private name: string) { }
// Decorator
@printExecution
printName() {
console.log(`Hello, my name is ${this.name}.`);
}
}
// Create an object of the class
const user = new Person("John");
// Accessing the properties of the class
user.printName();
輸出
start: printName Hello, my name is John.
訪問器裝飾器
訪問器裝飾器與 get() 和 set() 訪問器一起使用,以觀察、替換和修改訪問器的定義。
示例
// Decorator factory
function LogAccessor(method: any) {
console.log("Getter called");
}
// Define a class
class MyClass {
private _name: string = "MyClass";
// Decorator
@LogAccessor
get name() {
return this._name;
}
}
const instance = new MyClass();
console.log(instance.name);
輸出
Getter called MyClass
屬性裝飾器
屬性裝飾器與屬性一起使用,以修改、替換和觀察它。
示例
// Decorator function to log the property name
function LogProperty(target: any, propertyKey: string) {
console.log(`Property declared: ${propertyKey}`);
}
class Person {
// Decorator is applied to the property
@LogProperty
name: string;
@LogProperty
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
let person = new Person('Jay', 23);
輸出
Property declared: name Property declared: age
引數裝飾器
引數裝飾器與方法引數一起使用,以觀察、修改和替換它們。
示例
// Decorator with parameter
function LogParameter(target: any, methodName: string, parameterIndex: number) {
console.log(`Parameter in ${methodName} at index ${parameterIndex} has been decorated`);
}
// Class decorator
class MyClass {
myMethod(@LogParameter param: string) {
console.log(`Executing myMethod with param: ${param}`);
}
}
// Create an instance of the class
const instance = new MyClass();
instance.myMethod("test");
輸出
Parameter in myMethod at index 0 has been decorated Executing myMethod with param: test
我們已經學習瞭如何在 TypeScript 中建立自定義裝飾器。但是,使用者可以將預定義的裝飾器用於各種目的,例如除錯程式碼等。