MST

星途 面试题库

面试题:TypeScript装饰器在复杂项目架构中的优化与设计

假设你正在参与一个大型TypeScript项目的架构设计,项目中有大量的业务逻辑需要通过装饰器来实现切面编程。请阐述在这种场景下,如何设计装饰器以确保代码的可维护性、性能优化以及避免装饰器之间的冲突?给出具体的设计思路和关键代码示例。
27.8万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 单一职责原则:每个装饰器只负责一项明确的功能,例如日志记录、权限验证、性能监测等。这样使得装饰器功能清晰,易于理解和维护。
  2. 模块化:将不同功能的装饰器分模块进行管理,每个模块专注于特定的业务切面。例如,将所有与权限相关的装饰器放在 permission 模块中。
  3. 参数化:使装饰器可以接受参数,以增加其灵活性。例如,权限验证装饰器可以接受允许的权限列表作为参数。
  4. 顺序约定:制定装饰器应用顺序的约定,避免因顺序问题导致冲突。例如,规定日志记录装饰器总是在最外层,而业务逻辑相关装饰器在内部。
  5. 性能优化:在装饰器内部,避免复杂的初始化操作,尽量将计算延迟到实际调用时。同时,对于频繁调用的函数所应用的装饰器,要确保其操作高效。

关键代码示例

  1. 简单的日志记录装饰器
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;
}
  1. 带参数的权限验证装饰器
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;
    };
}
  1. 使用示例
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 项目中有效地设计装饰器,保证代码的可维护性、性能优化并避免装饰器之间的冲突。