面试题答案
一键面试使用 TypeScript 装饰器实现组件方法权限控制和日志记录
- 权限控制装饰器
// 权限控制装饰器 function checkPermission(permission: string) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = function (...args: any[]) { // 模拟获取当前用户权限 const userPermissions = ['admin', 'user:read']; if (userPermissions.includes(permission)) { return originalMethod.apply(this, args); } else { throw new Error('没有权限执行此操作'); } }; return descriptor; }; }
- 日志记录装饰器
// 日志记录装饰器 function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = function (...args: any[]) { console.log(`调用方法 ${propertyKey},参数:`, args); const result = originalMethod.apply(this, args); console.log(`方法 ${propertyKey} 返回结果:`, result); return result; }; return descriptor; }
- 使用装饰器
class MyComponent { @checkPermission('admin') @log importantMethod(data: string) { return `处理数据: ${data}`; } } const component = new MyComponent(); try { console.log(component.importantMethod('示例数据')); } catch (error) { console.error(error.message); }
优势
- 代码简洁清晰:将权限控制和日志记录等横切关注点从业务逻辑中分离出来,使组件方法的核心逻辑更清晰,减少重复代码。例如,多个组件方法需要相同的权限控制,只需在方法上添加装饰器,而无需在每个方法内部重复编写权限检查代码。
- 可维护性强:如果权限控制逻辑或日志记录方式发生变化,只需修改装饰器代码,所有使用该装饰器的方法都会受到影响,便于集中管理和维护。
- 增强代码可读性:通过装饰器可以直观地看到组件方法所具备的额外功能,如
@checkPermission('admin')
表明该方法需要管理员权限。
挑战
- 调试困难:装饰器会改变方法的执行逻辑,在调试时可能难以追踪原始方法的执行路径。尤其是多个装饰器叠加使用时,调用栈会变得复杂,增加调试难度。
- 性能开销:每次调用被装饰的方法时,都会执行装饰器内部的逻辑,虽然现代 JavaScript 引擎对此有一定优化,但在性能敏感的场景下,可能会对性能产生一定影响。
- 兼容性问题:装饰器是一项相对较新的特性,虽然 TypeScript 支持良好,但在一些老旧的 JavaScript 运行环境(如不支持 ES6 及以上特性的环境)中可能无法正常使用,需要进行额外的编译或转换处理。