TypeScript中装饰器的理解
前端面试题包括ECMScript,TypeScript,Nodejs,React,Webgl,Threejs等还在整理中,在线地址前端面试题,源码地址大家多多支持才有动力给大家分享更多好的面试题。
- 在 TypeScript 中,装饰器(Decorators)是一种特殊的语法,用于在类及其成员(如属性、方法、访问器)上添加元数据或修改行为。它们可以用于函数和类的注解,也可以用于动态修改类的行为。装饰器的核心概念是在不改变类本身逻辑的前提下,增强类的功能或控制类的行为。
装饰器的基本概念
-
装饰器本质上是一种函数,它可以应用到类、方法、访问器、属性或者参数上。装饰器在编译时执行,并且可以访问被装饰元素的元数据,从而对其进行操作或修改。装饰器通常用于元编程、依赖注入、日志记录、权限控制等场景。
-
TypeScript 中的装饰器可以应用在以下四个地方:
- 类装饰器:作用于整个类。
- 方法装饰器:作用于类的方法。
- 访问器装饰器:作用于属性的 getter 和 setter。
- 属性装饰器:作用于类的属性。
- 参数装饰器:作用于方法的参数。
启用装饰器
- 在 TypeScript 中使用装饰器,首先需要在 tsconfig.json 中启用 “experimentalDecorators” 选项:
{
"compilerOptions": {
"experimentalDecorators": true
}
}
类装饰器
- 类装饰器用于修改或增强整个类。它的形式是接受一个类构造函数作为参数,可以返回一个新的类或修改类的行为。
// 定义一个简单的类装饰器
function Logger(constructor: Function) {
console.log(`Creating new instance of ${constructor.name}`);
}
@Logger
class Person {
constructor(public name: string) {}
}
// 创建一个 Person 实例,触发装饰器
const john = new Person('John');
- 在上面的例子中,@Logger 是一个装饰器,它记录了类的创建过程。在 Person 类上应用了 @Logger 装饰器后,每当实例化这个类时,控制台都会输出类名。
方法装饰器
- 方法装饰器用于修改或增强类的方法。它接收三个参数:类的原型、方法的名称以及方法的属性描述符。通过装饰器,可以修改方法的行为或属性描述符。
// 定义一个方法装饰器
function LogMethod(
target: any,
propertyName: string,
descriptor: PropertyDescriptor,
) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(
`Calling ${propertyName} with arguments: ${JSON.stringify(args)}`,
);
return originalMethod.apply(this, args);
};
}
class Calculator {
@LogMethod
add(a: number, b: number): number {
return a + b;
}
}
const calc = new Calculator();
calc.add(2, 3); // 输出: Calling add with arguments: [2,3]
- 在这个例子中,@LogMethod 是一个方法装饰器,它拦截了 add 方法的调用并记录了参数信息,之后再执行原始方法逻辑。
访问器装饰器
- 访问器装饰器用于装饰类的 getter 或 setter 方法。它与方法装饰器类似,但只能用于访问器。
// 定义一个访问器装饰器
function CheckAge(
target: any,
propertyName: string,
descriptor: PropertyDescriptor,
) {
const originalSetter = descriptor.set;
descriptor.set = function (value: number) {
if (value < 0) {
throw new Error('Age cannot be negative');
}
originalSetter?.call(this, value);
};
}
class User {
private _age: number = 0;
@CheckAge
set age(value: number) {
this._age = value;
}
get age(): number {
return this._age;
}
}
const user = new User();
user.age = 25; // 正常设置
// user.age = -5; // 抛出错误: Age cannot be negative
- 在这个例子中,@CheckAge 是一个访问器装饰器,它确保年龄不能设置为负数。
属性装饰器
- 属性装饰器用于类的属性,主要用于元数据的记录,不能修改属性的行为。属性装饰器接收两个参数:类的原型和属性名称。
// 定义一个属性装饰器
function ReadOnly(target: any, propertyKey: string) {
console.log(`Setting up property: ${propertyKey}`);
}
class Car {
@ReadOnly
model: string;
constructor(model: string) {
this.model = model;
}
}
- 在上面的例子中,@ReadOnly 是一个属性装饰器,它不能改变属性本身的行为,但可以记录属性的元数据或添加其他额外逻辑。
参数装饰器
- 参数装饰器用于装饰方法的参数,它接收三个参数:类的原型、方法名以及参数的位置索引。参数装饰器通常用于依赖注入等场景。
// 定义一个参数装饰器
function LogParam(target: any, propertyKey: string, parameterIndex: number) {
console.log(
`Parameter of ${propertyKey} at index ${parameterIndex} is being decorated`,
);
}
class CarService {
getCar(@LogParam carId: number) {
console.log(`Fetching car with ID: ${carId}`);
}
}
const service = new CarService();
service.getCar(123); // 输出: Parameter of getCar at index 0 is being decorated
- 在这个例子中,@LogParam 是一个参数装饰器,用于记录方法参数的信息。
装饰器工厂
- 装饰器工厂是一个返回装饰器的函数,可以接受参数,从而让装饰器更加灵活。
// 定义一个装饰器工厂
function Log(message: string) {
return function (constructor: Function) {
console.log(message);
};
}
@Log('Logging for the User class')
class User {
constructor(public name: string) {}
}
- 在这个例子中,@Log(‘Logging for the User class’) 是一个装饰器工厂,它允许传递参数,灵活控制装饰器的行为。
装饰器的应用场景
- 依赖注入:装饰器常用于标注类的依赖关系,便于自动注入。
- 权限控制:可以在方法级别添加权限验证逻辑。
- 日志记录:通过装饰器对类或方法的调用进行日志记录。
- 元数据管理:可以使用装饰器为类添加元数据,用于框架或库的扩展。
总结
- 装饰器 是 TypeScript 中的一种增强功能,可以为类和类的成员添加元数据或修改其行为。
- 它可以应用在类、方法、属性、访问器、参数上,并通过函数的形式实现。
- 装饰器工厂 提供了更灵活的方式,通过函数传参控制装饰器行为。
- 常见的使用场景包括:依赖注入、日志记录、权限控制、元数据注解等。
原文地址:https://blog.csdn.net/qq_34820371/article/details/142863125
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!