TypeScript装饰器原理
- 本质:装饰器本质上是一个函数,它可以在运行时对类、方法、属性或参数进行元编程,修改它们的行为或添加额外功能。
- 工作机制:当装饰器应用到目标(类、方法等)时,它会在目标定义时被调用,并将目标对象作为参数传递给装饰器函数。对于类装饰器,会传入类的构造函数;方法装饰器传入类的原型、方法名和描述符;属性装饰器传入类的原型和属性名;参数装饰器传入类的原型、方法名和参数在参数列表中的索引。
权限控制装饰器实现
// 定义权限类型
type Permission = 'admin' | 'user' | 'guest';
// 模拟当前用户权限
const currentUserPermission: Permission = 'user';
// 权限控制装饰器
function checkPermission(requiredPermission: Permission) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
if (currentUserPermission === requiredPermission) {
return originalMethod.apply(this, args);
} else {
console.log('权限不足,无法执行该操作');
}
};
return descriptor;
};
}
class ExampleClass {
@checkPermission('admin')
adminOnlyMethod() {
console.log('这是只有管理员能访问的方法');
}
}
const example = new ExampleClass();
example.adminOnlyMethod();
在实际项目中集成
- 定义装饰器库:将权限控制装饰器相关代码封装成一个独立的库或模块,方便在项目中复用。
- 引入和使用:在需要进行权限控制的类和方法上引入装饰器并使用。可以在业务逻辑层的类方法上添加装饰器,比如在服务层的方法,只有特定权限的用户才能调用某些数据修改方法。
- 权限数据管理:实际项目中,当前用户权限
currentUserPermission
通常从后端获取,并存储在全局状态管理工具(如Redux、Vuex等)中。装饰器可以从全局状态中获取当前用户权限进行判断。
性能问题及解决方案
- 性能问题:
- 额外函数调用开销:装饰器会在原方法调用前后增加额外的函数调用,每次调用被装饰方法时都会执行装饰器中的逻辑,可能会影响性能,尤其是在频繁调用的方法上。
- 闭包内存占用:装饰器使用闭包来捕获外部变量(如
requiredPermission
),如果闭包中的变量在长时间内不释放,可能会导致内存泄漏,特别是在频繁创建和销毁被装饰对象的场景下。
- 解决方案:
- 缓存结果:对于不经常变化的权限判断结果,可以进行缓存。例如,如果在短时间内多次调用同一个被装饰方法,可以在第一次调用时判断权限并缓存结果,后续调用直接返回缓存结果。
- 优化闭包使用:尽量减少闭包中引用的外部变量数量,并且在不需要时及时释放闭包。比如可以将一些不变的配置参数作为装饰器函数的参数传入,而不是在闭包中引用全局变量。同时,在被装饰对象销毁时,确保闭包中引用的对象也能被正确释放。