MST
星途 面试题库

面试题:TypeScript 装饰器的基本使用场景

请举例说明 TypeScript 装饰器在前端开发中的三个基本使用场景,并简单描述如何实现。
21.1万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

场景一:属性装饰器 - 数据校验

  1. 使用场景:在前端开发中,经常需要对类的属性进行数据校验。例如,在一个用户信息类中,对邮箱属性进行格式校验。
  2. 实现方式
function validateEmail(target: any, propertyKey: string) {
    let value: string;
    const getter = function () {
        return value;
    };
    const setter = function (newValue: string) {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (!emailRegex.test(newValue)) {
            throw new Error('Invalid email format');
        }
        value = newValue;
    };
    if (delete target[propertyKey]) {
        Object.defineProperty(target, propertyKey, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
    }
}

class User {
    @validateEmail
    email: string;
}

const user = new User();
user.email = "test@example.com"; 
// user.email = "testexample.com"; // 会抛出错误

场景二:方法装饰器 - 日志记录

  1. 使用场景:在前端开发中,对于一些关键的方法调用,希望记录方法的调用信息,比如方法名、参数等,方便调试和追踪。例如,在一个订单提交方法上记录调用信息。
  2. 实现方式
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;
}

class OrderService {
    @log
    submitOrder(order: any) {
        // 订单提交逻辑
        return "Order submitted successfully";
    }
}

const orderService = new OrderService();
orderService.submitOrder({ amount: 100 }); 

场景三:类装饰器 - 自动绑定 this

  1. 使用场景:在前端开发中,尤其是在 React 或 Vue 等框架中,类的方法内部经常需要正确绑定 this。使用类装饰器可以自动为所有方法绑定 this
  2. 实现方式
function autoBind(target: any) {
    const originalPrototype = target.prototype;
    for (const methodName of Object.getOwnPropertyNames(originalPrototype)) {
        const descriptor = Object.getOwnPropertyDescriptor(originalPrototype, methodName);
        if (typeof descriptor.value === 'function') {
            originalPrototype[methodName] = descriptor.value.bind(originalPrototype);
        }
    }
    return target;
}

@autoBind
class Component {
    data = { message: 'Hello' };
    printMessage() {
        console.log(this.data.message);
    }
}

const component = new Component();
component.printMessage();