MST

星途 面试题库

面试题:TypeScript属性装饰器的元编程与AOP实现

在TypeScript中,结合属性装饰器实现面向切面编程(AOP),例如实现一个日志切面,当类的某个属性被访问或修改时,记录详细的操作日志,包括操作时间、操作类型、操作前后的属性值等。要求考虑如何通过元编程技术,使这个日志切面可以灵活应用于不同类的多个属性上,且对业务代码的侵入性最小。请详细描述实现步骤并给出核心代码。
34.6万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
  1. 定义日志切面装饰器
    • 使用属性装饰器,在装饰器内部通过Reflect API来存储和获取属性相关信息。
    • 定义一个LogAspect装饰器,接收一个参数message用于日志记录的描述。
function LogAspect(message: string) {
    return function (target: any, propertyKey: string) {
        let value: any;
        const descriptor: PropertyDescriptor = {
            get() {
                const operationTime = new Date().toISOString();
                const operationType = 'get';
                const preValue = value;
                const postValue = value;
                console.log(`${operationTime} - ${operationType} - ${message} - preValue: ${preValue}, postValue: ${postValue}`);
                return value;
            },
            set(newValue: any) {
                const operationTime = new Date().toISOString();
                const operationType ='set';
                const preValue = value;
                value = newValue;
                const postValue = value;
                console.log(`${operationTime} - ${operationType} - ${message} - preValue: ${preValue}, postValue: ${postValue}`);
            }
        };
        return descriptor;
    };
}
  1. 在类中使用装饰器
    • 创建一个类,为类的属性应用LogAspect装饰器。
class ExampleClass {
    @LogAspect('Example property operation')
    exampleProperty: string;

    constructor() {
        this.exampleProperty = 'initial value';
    }
}
  1. 测试代码
    • 创建类的实例,并访问和修改属性,观察日志输出。
const example = new ExampleClass();
console.log(example.exampleProperty);
example.exampleProperty = 'new value';

通过上述步骤,我们利用TypeScript的属性装饰器实现了一个日志切面,它可以灵活应用于不同类的多个属性上,并且对业务代码的侵入性较小。通过元编程技术(这里主要是Reflect API的使用),我们能够在不改变属性原有逻辑太多的情况下,添加日志记录功能。