MST

星途 面试题库

面试题:TypeScript 中装饰器如何实现简单的面向切面编程

请描述在TypeScript中,使用装饰器实现一个简单的面向切面编程场景,比如在方法调用前后打印日志。请给出具体代码示例,并解释其原理。
22.5万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

代码示例

// 定义一个日志装饰器
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 ExampleClass {
    @log
    exampleMethod(a: number, b: number) {
        return a + b;
    }
}

const example = new ExampleClass();
example.exampleMethod(1, 2);

原理解释

  1. 装饰器定义:装饰器本质上是一个函数,它接受三个参数:target(被装饰的目标,对于方法装饰器来说是类的原型对象)、propertyKey(被装饰的属性名,即方法名)、descriptor(属性描述符,包含了该方法的一些元信息,如valuewritable等)。
  2. 保存原始方法:在装饰器函数中,我们首先保存原始方法的引用originalMethod,以便后续正常调用。
  3. 方法重定义:我们重新定义descriptor.value,也就是实际调用的方法。在新的方法中,先打印调用前的日志,包含方法名和传入的参数。然后通过apply方法调用原始方法,并传递this上下文和参数,获取返回值。最后打印调用后的日志,包含方法名和返回值。
  4. 类中使用:在ExampleClass类的exampleMethod方法上使用@log装饰器,这样当调用exampleMethod时,就会触发装饰器中定义的逻辑,在方法调用前后打印日志。