TypeScript 中的装饰器
本文解释了 TypeScript 中的装饰器。
YouTube Video
TypeScript 中的装饰器
TypeScript 装饰器是一种为类、方法、访问器、属性或参数添加额外功能或行为的机制。装饰器是增强代码可读性和可重用性的强大工具。
装饰器的基础
装饰器是一种为类或类成员注入额外功能的函数。装饰器是在 TypeScript 1.5 中引入的,并已被提议纳入 ECMAScript 标准。
1{
2 "compilerOptions": {
3 "experimentalDecorators": true
4 }
5}- 要使用装饰器,您需要在
tsconfig.json文件中启用experimentalDecorators选项。
装饰器的类型
在 TypeScript 中,您可以使用以下五种装饰器。
- 类装饰器 应用于类的装饰器。
- 方法装饰器 应用于类方法的装饰器。
- 访问器装饰器 应用于类属性的 getter 或 setter 的装饰器。
- 属性装饰器 应用于类属性的装饰器。
- 参数装饰器 应用于方法参数的装饰器。
类装饰器
类装饰器是应用于类的装饰器。类装饰器写在类定义的正上方,可以访问类的构造函数。它们主要用于更改类的行为或添加元数据。
1function Logger(constructor: Function) {
2 console.log(`Class ${constructor.name} is being constructed`);
3}
4
5@Logger
6class Person {
7 constructor(public name: string) {}
8}
9
10const person = new Person('John');
11// Output: Class Person is being constructed
在此示例中,Logger 装饰器应用于类,并在类初始化时在控制台中显示一条消息。
方法装饰器
方法装饰器应用于类方法,可以更改方法的调用和行为。方法装饰器接收三个参数。
- 类的原型
- 方法的名称
- 方法的属性描述符
1function LogExecutionTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
2 const originalMethod = descriptor.value;
3
4 descriptor.value = function (...args: any[]) {
5 console.time(propertyKey);
6 const result = originalMethod.apply(this, args);
7 console.timeEnd(propertyKey);
8 return result;
9 };
10}
11
12class MathOperations {
13 @LogExecutionTime
14 add(a: number, b: number): number {
15 return a + b;
16 }
17}
18
19const math = new MathOperations();
20math.add(2, 3);
21// Output: add: 0.000ms (execution time is displayed)
在此示例中,将 LogExecutionTime 装饰器应用于方法,并记录方法的执行时间。
访问器装饰器
访问器装饰器应用于类属性的 getter 或 setter。它们在修改属性值时用于添加行为。
1function LogAccess(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
2 const originalGet = descriptor.get;
3 const originalSet = descriptor.set;
4
5 if (originalGet) {
6 descriptor.get = function () {
7 console.log(`Getter called for ${propertyKey}`);
8 return originalGet.call(this);
9 };
10 }
11
12 if (originalSet) {
13 descriptor.set = function (value: any) {
14 console.log(`Setter called for ${propertyKey} with value: ${value}`);
15 originalSet.call(this, value);
16 };
17 }
18}
19
20class Car {
21 private _speed: number = 0;
22
23 @LogAccess
24 get speed() {
25 return this._speed;
26 }
27
28 set speed(value: number) {
29 this._speed = value;
30 }
31}
32
33const car = new Car();
34car.speed = 120; // Setter called for speed with value: 120
35console.log(car.speed); // Getter called for speed → 120
在这个例子中,当调用 getter 和 setter 时,使用了一个访问器装饰器来记录输出。
属性装饰器
属性装饰器应用于类属性,但不能直接更改属性的值或行为。它们用于获取属性的元数据。
1function Readonly(target: any, propertyKey: string) {
2 Object.defineProperty(target, propertyKey, {
3 writable: false
4 });
5}
6
7class Book {
8 @Readonly
9 title: string = "TypeScript Guide";
10}
11
12const book = new Book();
13book.title = "New Title"; // Error: Cannot assign to read only property 'title'
在此示例中,将 Readonly 装饰器应用于 title 属性,使该属性成为只读。
参数装饰器
参数装饰器应用于方法的参数。它们通常用于存储元数据或验证参数。装饰器接收三个参数。
- 类的原型
- 方法的名称
- 参数索引
1function LogParameter(target: any, propertyKey: string, parameterIndex: number) {
2 console.log(`Parameter at index ${parameterIndex} in method ${propertyKey} was decorated.`);
3}
4
5class User {
6 greet(@LogParameter message: string) {
7 console.log(message);
8 }
9}
10
11const user = new User();
12user.greet('Hello!');
13// Output: Parameter at index 0 in method greet was decorated.
在此示例中,将 LogParameter 装饰器应用于 greet 方法的第一个参数,当调用此方法时,会记录该参数已被装饰。
装饰器的实际示例
装饰器广泛用于例如 Angular 这样的框架,尤其是在依赖注入和元数据定义方面。例如,可以使用 @Component 装饰器来定义类似如下的 Angular 组件。
1@Component({
2 selector: 'app-root',
3 template: '<h1>Hello World</h1>',
4})
5export class AppComponent {}因此,装饰器通常作为框架和库的核心部分使用,有助于保持代码简洁明了。
装饰器总结
TypeScript 装饰器是强大的工具,可以灵活地为类、方法和属性添加功能。使用自定义装饰器可以提高代码的可维护性和可复用性,从而实现更高的抽象。装饰器在像Angular和NestJS这样的框架中起着重要作用,理解它们有助于深入了解这些框架的工作原理。
您可以在我们的YouTube频道上使用Visual Studio Code跟随上述文章进行学习。 请也查看我们的YouTube频道。