面试题答案
一键面试设计思路
- 单一职责原则:每个装饰器只负责一项明确的功能,例如日志记录、权限验证、性能监测等。这样使得装饰器功能清晰,易于理解和维护。
- 模块化:将不同功能的装饰器分模块进行管理,每个模块专注于特定的业务切面。例如,将所有与权限相关的装饰器放在
permission
模块中。 - 参数化:使装饰器可以接受参数,以增加其灵活性。例如,权限验证装饰器可以接受允许的权限列表作为参数。
- 顺序约定:制定装饰器应用顺序的约定,避免因顺序问题导致冲突。例如,规定日志记录装饰器总是在最外层,而业务逻辑相关装饰器在内部。
- 性能优化:在装饰器内部,避免复杂的初始化操作,尽量将计算延迟到实际调用时。同时,对于频繁调用的函数所应用的装饰器,要确保其操作高效。
关键代码示例
- 简单的日志记录装饰器
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling method ${propertyKey} with arguments:`, args);
const result = originalMethod.apply(this, args);
console.log(`Method ${propertyKey} returned:`, result);
return result;
};
return descriptor;
}
- 带参数的权限验证装饰器
function checkPermissions(permissions: string[]) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
// 模拟权限检查逻辑
const hasPermission = true; // 实际应根据当前用户权限判断
if (hasPermission) {
return originalMethod.apply(this, args);
} else {
throw new Error('Permission denied');
}
};
return descriptor;
};
}
- 使用示例
class MyService {
@log
@checkPermissions(['read', 'write'])
public doSomething(data: string) {
return `Processed data: ${data}`;
}
}
const service = new MyService();
try {
const result = service.doSomething('Hello');
console.log(result);
} catch (error) {
console.error(error);
}
通过以上设计思路和代码示例,可以在大型 TypeScript 项目中有效地设计装饰器,保证代码的可维护性、性能优化并避免装饰器之间的冲突。