Inhaltsverzeichnis
Einführung
In TypeScript sind Dekoratoren ein Werkzeug für die Metaprogrammierung. Der TypeScript-Dekorator ist eine seiner leistungsstärksten Metaprogrammierungsfunktionen. Er kann Metadaten und Verhalten zu Klassen, Methoden, Eigenschaften und Parametern hinzufügen. Er kann die Codestruktur ändern, ohne die Codelogik zu ändern. Kommentieren, erweitern, ändern und umgestalten, um den Code besser zu machen elegant, prägnant, wartbar und leicht erweiterbar. Es handelt sich um eine relativ neue Sprachfunktion, die jedoch in verschiedenen Frameworks und Bibliotheken wie Angular, NestJS, Express usw. weit verbreitet ist.
In diesem Artikel untersuchen wir die Funktionen und Verwendungsszenarien von TypeScript-Dekoratoren.
Einführung in Dekorateure
Ein Dekorator ist eine besondere Art , die zum Dekorieren von , und 函数
verwendet werden kann , indem diesen Objekten Dekoratoren hinzugefügt werden . Seine Syntax ähnelt einem Kommentar, aber was er wirklich tut, ist .类
属性
方法
参数
改变它们的行为
在代码编译阶段进行元编程操作
Grundlegende Syntax für Dekorateure
Folgendermaßen:
@decorator
class MyClass {
// class implementation
}
@decorator
function MyFunction() {
// function implementation
}
@decorator
property MyProperty {
// property implementation
}
@decorator
method MyMethod() {
// method implementation
}
@decorator
parameter MyParameter {
// parameter implementation
}
- In TypeScript ist ein Dekorator eine Funktion oder ein Ausdruck, der je nach Kontext, in dem der Dekorator angewendet wird, ein oder mehrere Argumente annimmt.
Fügen Sie Metadaten zu Klassen hinzu
-
Hier ist ein Beispiel für einen einfachen Dekorator, der einer Klasse Metadaten hinzufügt:
function MyClassDecorator(target: Function) { Reflect.defineMetadata("custom:my-metadata", "Hello, world!", target); } @MyClassDecorator class MyClass { // class implementation }
-
In diesem Dekorator verwenden wir die Reflection-API von TypeScript,
Reflect
um Metadaten hinzuzufügen. Der Schlüssel dieser Metadaten ist „custom:my-metadata“ und der Wert ist „Hello, world!“. Der Dekorator wirdMyClass
auf .MyClassDecorator
Wenn er aufgerufen wird,target
istMyClass
diese Funktion. Wir können diese Metadaten für nachfolgende Vorgänge wie Serialisierung und Deserialisierung verwenden. So erhalten Sie diese Metadaten:const metadata = Reflect.getMetadata("custom:my-metadata", MyClass); console.log(metadata); // Output: "Hello, world!"
-
In diesem Beispiel
Reflect
haben wirgetMetadata
die Methode verwendet, um die Metadaten abzurufen. Der erste Parameter dieser Methode ist der Schlüssel der Metadaten und der zweite Parameter ist die Funktion, die diese Metadaten definiert.
Verhalten hinzufügen
- Zusätzlich zum Hinzufügen von Metadaten können Dekorateure auch Verhalten hinzufügen. Hier ist ein Beispiel für das Hinzufügen eines Verhaltens, das Setter und Getter zu Eigenschaften einer Klasse hinzufügt:
function MyPropertyDecorator(target: any, propertyKey: string) { // property getter const getter = function () { console.log(`Getting value for ${ propertyKey}`); return this[`_${ propertyKey}`]; }; // property setter const setter = function (newVal) { console.log(`Setting value for ${ propertyKey}`); this[`_${ propertyKey}`] = newVal; }; // delete and redefine the property if (delete this[propertyKey]) { Object.defineProperty(target, propertyKey, { get: getter, set: setter, enumerable: true, configurable: true }); } } class MyClass { @MyPropertyDecorator myProp: string; }
- In diesem Beispiel definieren wir einen Dekorator
MyPropertyDecorator
namens dermyProp
auf die Eigenschaft angewendet wird. Wenn der Dekorator angewendet wird, definiert er den Getter und Setter der Eigenschaft neu. In diesem Beispiel können wirmyProp
Eigenschafts- um das Get- und Set-Verhalten zu dokumentieren.
Verwendungsszenarien von TypeScript-Dekoratoren
日志记录
- Dekorateure können Protokolle aufzeichnen, sodass Entwickler den Ausführungsstatus des Programms verstehen und das Debuggen und Optimieren des Programms erleichtern können.
function log(target: Function) { console.log(`Logger: ${ target.name} constructed.`) } @log class MyClass { constructor() { } } // output: Logger: MyClass constructed.
- In diesem Beispiel wird das Dekorator-Funktionsprotokoll auf den Konstruktor der MyClass-Klasse angewendet. Wenn der Code kompiliert wird, ändert der Dekorator das Verhalten von MyClass, sodass das Protokoll gedruckt wird, wenn der Konstruktor aufgerufen wird.
- Dekorateure können Protokolle aufzeichnen, sodass Entwickler den Ausführungsstatus des Programms verstehen und das Debuggen und Optimieren des Programms erleichtern können.
校验
- Dekorateure können Klassen und Eigenschaften validieren, um sicherzustellen, dass sie bestimmten Spezifikationen entsprechen.
// 类装饰器 function validateClass(target: any) { // 检查类是否有name属性 if (!target.name) { throw new Error("Class name is required"); } } // 属性装饰器 function validateProperty(target: any, propertyKey: string) { // 获取属性值 const value = target[propertyKey]; // 检查属性值是否为数字 if (typeof value !== "number") { throw new Error(`${ propertyKey} must be a number`); } } @validateClass class Person { name: string; @validateProperty age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } } // 创建一个Person实例 const person = new Person("Bob", 25); // 输出实例的属性 console.log(person.name); // "Bob" console.log(person.age); // 25 // 创建一个不合法的Person实例 const invalidPerson = new Person("", "25"); // 抛出类装饰器抛出的异常 // Error: Class name is required // 创建一个属性不合法的Person实例 const invalidAgePerson = new Person("Bob", "25"); // 抛出属性装饰器抛出的异常 // Error: age must be a number
- Dieses Beispiel definiert zwei Dekoratorfunktionen
validateClass
undvalidateProperty
.validateClass
Wird verwendet, um zu überprüfen, ob eine Klasse übername
eine Eigenschaft , und um eine Ausnahme auszulösen, wenn dies nicht der Fall ist.validateProperty
Wird verwendet, um zu prüfen, ob der Attributwert einer Klasse eine Zahl ist, und um eine Ausnahme auszulösen, wenn dies nicht der Fall ist. - Dekorieren Sie im
Person
Unterricht@validateClass
die Klasse mit dem Dekorateur@validateProperty
und dekorieren Sieage
das Grundstück mit dem Dekorateur. Wenn beim ErstellenPerson
einer Instanz die Attribute der Klasse nicht den Anforderungen entsprechen, wird die entsprechende Ausnahme ausgelöst.
- Dekorateure können Klassen und Eigenschaften validieren, um sicherzustellen, dass sie bestimmten Spezifikationen entsprechen.
性能优化
- Dekorateure können die Leistung des Codes optimieren, indem sie beispielsweise einige Berechnungsergebnisse zwischenspeichern, um wiederholte Berechnungen zu vermeiden.
function memoize(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; const cache = new Map(); descriptor.value = function(...args) { const key = JSON.stringify(args); if (cache.has(key)) { return cache.get(key); } const result = originalMethod.apply(this, args); cache.set(key, result); return result; }; return descriptor; } class Calculator { @memoize factorial(n: number): number { console.log(`Calculating factorial of ${ n}`); if (n === 0) { return 1; } return n * this.factorial(n - 1); } } const calc = new Calculator(); console.log(calc.factorial(5)); // Calculating factorial of 5, 120 console.log(calc.factorial(5)); // 120 console.log(calc.factorial(10)); // Calculating factorial of 10, 3628800 console.log(calc.factorial(10)); // 3628800
- In diesem Beispiel wird eine Dekoratorfunktion definiert,
memoize
um das Berechnungsergebnis einer bestimmten Methode der Klasse zwischenzuspeichern. Rufen Sie inmemoize
der Funktion zuerst die ursprüngliche Methode ab und erstellen Sie dann einen CacheMap
. Überschreibt die ursprüngliche Methode und konvertiert beim Aufruf das übergebene Argument in eine Zeichenfolge als Cache-Schlüssel. Wenn im Cache bereits ein diesem Schlüssel entsprechender Wert vorhanden ist, wird das Ergebnis im Cache direkt zurückgegeben, andernfalls wird das Ergebnis der Methode berechnet und im Cache gespeichert. - Verwenden Sie in
Calculator
der Klasse@memoize
den Dekorator, umfactorial
die Methode , dh diese Methode in eine Methode mit Caching-Funktion umzuwandeln. Rufen Sie die Methode nach dem ErstellenCalculator
der Instanzfactorial
zweimal auf: Beim ersten Mal müssen Sie die Fakultät berechnen, und beim zweiten Mal erhalten Sie den Fakultätswert direkt aus dem Cache, um wiederholte Berechnungen zu vermeiden.
- Dekorateure können die Leistung des Codes optimieren, indem sie beispielsweise einige Berechnungsergebnisse zwischenspeichern, um wiederholte Berechnungen zu vermeiden.
错误处理
- Dekorateure können Fehler im Programm behandeln, z. B. Ausnahmen abfangen und Fehlermeldungen ausgeben, was für Entwickler praktisch ist, um Fehler zu überprüfen und zu beseitigen.
function catchError(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; // 保存原始方法 descriptor.value = function (...args: any[]) { try { return originalMethod.apply(this, args); // 调用原始方法并返回结果 } catch (error) { console.error(`Error occurred in ${ propertyKey}:`, error); // 输出错误信息 } }; } class Example { @catchError public divide(a: number, b: number): number { return a / b; // 可能会抛出异常 } } const example = new Example(); example.divide(10, 0); // 调用方法,抛出异常并输出错误信息
- In diesem Beispiel definieren wir einen
catchError
Dekorator und wenden ihn auf die MethodeExample
der Klasse an.divide
Wenn wirexample.divide(10, 0)
die Methode , wird eine Ausnahme ausgelöst, da der Divisor 0 ist. Dieser Dekorator fängt die Ausnahme ab und gibt eine Fehlermeldung aus.
- Dekorateure können Fehler im Programm behandeln, z. B. Ausnahmen abfangen und Fehlermeldungen ausgeben, was für Entwickler praktisch ist, um Fehler zu überprüfen und zu beseitigen.
- Zusätzlich zu den oben genannten Beispielen können Dekoratoren auch in vielen anderen Situationen verwendet werden, z. B.
控制访问权限
,验证输入参数
usw.缓存数据
, wodurch Entwickler ein flexibleres und leistungsfähigeres Metaprogrammierungstool erhalten.
Zusammenfassen
Dekoratoren sind ein sehr leistungsfähiges Metaprogrammierungstool, das die Wartbarkeit und Erweiterbarkeit von TypeScript erheblich verbessern kann. Dekorateure können Metadaten und Verhalten zu Klassen, Methoden, Eigenschaften und Parametern hinzufügen. Mithilfe von Dekoratoren können Entwickler Code bequemer verwalten und ihn einfacher erweitern und ändern.