MST

星途 面试题库

面试题:TypeScript装饰器基础与AOP应用原理

请简要描述TypeScript装饰器的类型有哪些,并说明在AOP(面向切面编程)中,装饰器是如何实现对原有方法或类进行功能增强的?
31.6万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

TypeScript装饰器类型

  1. 类装饰器:作用于类的定义,可用于修改类的定义,比如添加新的属性、方法,或者修改类的原型。示例:
function classDecorator(target: Function) {
    target.prototype.newMethod = function() {
        console.log('This is a new method added by the class decorator');
    };
}

@classDecorator
class MyClass {}

const myObj = new MyClass();
(myObj as any).newMethod(); 
  1. 方法装饰器:作用于类的方法,可用于修改方法的属性描述符,比如改变方法的可枚举性、可写性等,或者在方法调用前后添加额外逻辑。示例:
function methodDecorator(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function() {
        console.log('Before method execution');
        const result = originalMethod.apply(this, arguments);
        console.log('After method execution');
        return result;
    };
    return descriptor;
}

class AnotherClass {
    @methodDecorator
    myMethod() {
        console.log('Inside myMethod');
    }
}

const anotherObj = new AnotherClass();
anotherObj.myMethod(); 
  1. 属性装饰器:作用于类的属性,可用于在类的属性定义时添加元数据等操作。示例:
function propertyDecorator(target: Object, propertyKey: string) {
    // 这里可以添加元数据等操作,例如:
    Reflect.defineMetadata('key', 'value', target, propertyKey);
}

class PropertyClass {
    @propertyDecorator
    myProperty: string;
}

const propertyObj = new PropertyClass();
const metadata = Reflect.getMetadata('key', propertyObj,'myProperty');
console.log(metadata); 
  1. 参数装饰器:作用于类方法的参数,可用于收集方法参数的元数据等。示例:
function parameterDecorator(target: Object, propertyKey: string, parameterIndex: number) {
    // 这里可以收集参数元数据等操作,例如:
    const existingMetadata = Reflect.getMetadata('parameters', target, propertyKey) || [];
    existingMetadata.push(parameterIndex);
    Reflect.defineMetadata('parameters', existingMetadata, target, propertyKey);
}

class ParameterClass {
    myFunction(@parameterDecorator param: string) {
        // 方法体
    }
}

const parameterObj = new ParameterClass();
const paramMetadata = Reflect.getMetadata('parameters', parameterObj,'myFunction');
console.log(paramMetadata); 

在AOP中装饰器实现功能增强的方式

  1. 前置增强:在方法装饰器中,通过保存原始方法,然后在新的函数中添加前置逻辑,再调用原始方法。如上述方法装饰器示例,在 originalMethod.apply(this, arguments) 之前添加的 console.log('Before method execution') 就是前置增强。
  2. 后置增强:同样在方法装饰器中,在调用原始方法之后添加逻辑,如 console.log('After method execution') 就是后置增强。
  3. 环绕增强:实际上上述方法装饰器示例就是环绕增强的一种形式,它既包含前置逻辑又包含后置逻辑,将原始方法调用包裹在中间。
  4. 异常处理增强:在方法装饰器中,可在调用原始方法的 try - catch 块中处理异常,实现异常处理的增强。示例:
function exceptionHandlerDecorator(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function() {
        try {
            return originalMethod.apply(this, arguments);
        } catch (error) {
            console.log('Exception caught:', error);
        }
    };
    return descriptor;
}

class ExceptionClass {
    @exceptionHandlerDecorator
    riskyMethod() {
        throw new Error('Simulated error');
    }
}

const exceptionObj = new ExceptionClass();
exceptionObj.riskyMethod(); 

通过这些方式,装饰器能够在不修改原有方法或类核心逻辑的情况下,为其添加额外功能,实现AOP的功能增强。