Laucher
2022年 10月 23日
0
TypeScript的装饰器
TypeScript 装饰器是一种特殊类型的声明,它可以附加到类、方法、属性或参数上,用于修改类的行为或添加额外的元数据。装饰器是一种在编译时进行元编程的技术,它使得我们可以以声明性的方式对类和类成员进行扩展或修改,而无需修改原始类的代码。
装饰器的定义和使用方法
装饰器是一种特殊类型的声明,通过 @
符号后跟一个装饰器工厂函数来表示。装饰器工厂函数接收不同的参数,并返回一个装饰器函数。装饰器函数可以在类定义时被调用,用于修改类的行为或添加额外的元数据。
类装饰器
类装饰器用于修饰类的构造函数。它接收一个参数,即目标类的构造函数。
function classDecorator(constructor: Function) {
console.log("Class Decorator");
}
@classDecorator
class MyClass {
// 类的定义
}
在上述例子中,classDecorator
是一个类装饰器,它在 MyClass
类定义时被调用,输出 “Class Decorator”。
方法装饰器
方法装饰器用于修饰类的方法。它接收三个参数:目标类的原型对象,方法的名称和方法的属性描述符。
function methodDecorator(target: any, methodName: string, descriptor: PropertyDescriptor) {
console.log("Method Decorator");
}
class MyClass {
@methodDecorator
myMethod() {
// 方法的定义
}
}
在上述例子中,methodDecorator
是一个方法装饰器,它在 myMethod
方法定义时被调用,输出 “Method Decorator”。
属性装饰器
属性装饰器用于修饰类的属性。它接收两个参数:目标类的原型对象和属性的名称。
function propertyDecorator(target: any, propertyName: string) {
console.log("Property Decorator");
}
class MyClass {
@propertyDecorator
myProperty: number;
}
在上述例子中,propertyDecorator
是一个属性装饰器,它在 myProperty
属性定义时被调用,输出 “Property Decorator”。
参数装饰器
参数装饰器用于修饰类的方法参数。它接收三个参数:目标类的原型对象、方法的名称和参数的索引。
function parameterDecorator(target: any, methodName: string, parameterIndex: number) {
console.log("Parameter Decorator");
}
class MyClass {
myMethod(@parameterDecorator param: string) {
// 方法的定义
}
}
在上述例子中,parameterDecorator
是一个参数装饰器,它在 myMethod
方法的参数 param
定义时被调用,输出 “Parameter Decorator”。
装饰器的应用场景
装饰器在 TypeScript 中有许多应用场景,它可以用于:
- 日志记录:通过方法装饰器来记录方法的调用和参数,实现日志记录功能。
function log(target: any, methodName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`用参数 ${args.join(", ")}调用${methodName}`);
return originalMethod.apply(this, args);
};
}
class MyClass {
@log
myMethod(name: string) {
console.log(`Hello, ${name}!`);
}
}
const instance = new MyClass();
instance.myMethod("Laucher");
// 输出:
// 用参数Laucher调用myMethod
// Hello, Laucher!
- 权限控制:通过方法装饰器来检查用户权限,实现权限控制功能。
function checkPermission(target: any, methodName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
if (userHasPermission()) {
return originalMethod.apply(this, args);
} else {
console.log("Permission denied.");
}
};
}
class MyClass {
@checkPermission
sensitiveOperation() {
// 敏感操作的实现
}
}
- 数据校验:通过属性装饰器来检查属性的合法性,实现数据校验功能。
function validate(target: any, propertyName: string) {
let value = target[propertyName];
const getter = function () {
return value;
};
const setter = function (newValue: number) {
if (newValue < 0) {
throw new Error("Value必须 >= 0");
}
value = newValue;
};
Object.defineProperty(target, propertyName, {
get: getter,
set: setter,
});
}
class MyClass {
@validate
price: number;
}
const instance = new MyClass();
instance.price = 100; // 有效
instance.price = -50; // 抛出错误:VValue必须 >= 0
- 路由映射:通过类装饰器和方法装饰器来映射路由,实现路由控制功能。
function route(path: string) {
return function (target: Function) {
// 实现路由映射逻辑
};
}
function get(target: any, methodName: string, descriptor: PropertyDescriptor) {
// 实现路由映射逻辑
}
@route("/users")
class UserController {
@get
getUsers() {
// 获取用户列表的实现
}
}
- 依赖注入:通过类装饰器和参数装饰器来实现依赖注入,简化类的构造函数注入依赖的过程。
const ServiceToken = Symbol("ServiceToken");
function injectService(target: any, propertyName: string, parameterIndex: number) {
const service = getServiceInstance();
target[propertyName] = service;
}
class MyClass {
constructor(@injectService private service: Service) {
// 类的构造函数
}
doSomething() {
this.service.doSomething();
}
}
- 性能监测:通过方法装饰器来监测方法的执行时间,实现性能监测功能。
function performanceMonitor(target: any, methodName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
const start = performance.now();
const result = originalMethod.apply(this, args);
const end = performance.now();
console.log(`方法 ${methodName}的执行时间为${end - start}毫秒。`);
return result;
};
}
class MyClass {
@performanceMonitor
heavyOperation() {
// 重型操作的实现
// 例如:排序大数组、复杂计算等
}
}
const instance = new MyClass();
instance.heavyOperation();
// 输出:方法heavyOperation的执行时间为123.45毫秒。