MST
星途 面试题库

面试题:TypeScript 5.0 装饰器标准演进下的装饰器组合应用与性能优化

在TypeScript 5.0的装饰器标准下,要求实现一个复杂场景:一个类有多个属性和方法,同时需要应用多个装饰器,包括属性装饰器、方法装饰器和类装饰器。这些装饰器之间存在依赖关系,例如属性装饰器可能需要基于类装饰器设置的某些全局状态来工作。请设计并实现这样一个示例,并详细说明如何在保证装饰器功能正确的前提下,进行性能优化,避免因装饰器的层层嵌套和多次调用带来的性能损耗。
30.6万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

1. 实现示例

// 类装饰器,设置全局状态
function globalStateClassDecorator(target: Function) {
    const globalState = { message: 'This is a global state' };
    Reflect.defineMetadata('globalState', globalState, target);
    return target;
}

// 属性装饰器,依赖类装饰器设置的全局状态
function dependentPropertyDecorator(target: Object, propertyKey: string | symbol) {
    const globalState = Reflect.getMetadata('globalState', target.constructor);
    console.log(`Using global state in property decorator: ${globalState.message}`);
}

// 方法装饰器
function methodDecorator(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
        console.log('Before method execution');
        const result = originalMethod.apply(this, args);
        console.log('After method execution');
        return result;
    };
    return descriptor;
}

@globalStateClassDecorator
class ComplexClass {
    @dependentPropertyDecorator
    property: string;

    constructor(property: string) {
        this.property = property;
    }

    @methodDecorator
    complexMethod() {
        console.log('Complex method is running');
    }
}

const instance = new ComplexClass('example value');
instance.complexMethod();

2. 性能优化

  • 减少不必要的计算
    • 在装饰器内部,只进行必要的操作,避免在每次装饰器调用时重复计算相同的结果。例如在dependentPropertyDecorator中,通过Reflect.getMetadata获取一次全局状态,而不是每次调用都重新计算。
  • 缓存结果
    • 如果装饰器的计算结果是不变的,可以进行缓存。比如对于类装饰器设置的全局状态,可以缓存下来供属性装饰器使用,避免多次从元数据中获取。
  • 合理使用元数据
    • 使用Reflect.metadata来存储和读取装饰器相关的数据,避免在装饰器链中传递大量的数据,减少传递过程中的性能开销。
  • 避免嵌套过深
    • 在设计装饰器时,尽量避免装饰器之间出现过深的嵌套关系。如果可能,将复杂的逻辑拆分成多个简单的装饰器,每个装饰器专注于单一职责,这样可以减少调用栈的深度,提高性能。