MST

星途 面试题库

面试题:TypeScript 装饰器在复杂继承结构中的执行顺序及规则

有一个类继承结构,基类 `BaseClass` 有一个方法 `baseMethod` 并应用了装饰器 `@baseDecorator`。子类 `SubClass` 继承自 `BaseClass` 并重写了 `baseMethod`,同时在 `SubClass` 的 `baseMethod` 上又应用了 `@subDecorator`。请深入分析这种情况下装饰器的执行顺序,以及不同类型的装饰器(类装饰器、方法装饰器等)在继承结构中遵循的规则。编写完整的 TypeScript 代码示例,并详细阐述整个执行过程和规则。
39.0万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

装饰器执行顺序及规则分析

  1. 装饰器执行顺序
    • 在 TypeScript 中,装饰器的执行顺序是从最内层到最外层。对于方法装饰器,先执行方法自身的装饰器,再执行继承自基类的装饰器。在本题中,先执行 @subDecorator,再执行 @baseDecorator
  2. 类装饰器和方法装饰器在继承结构中的规则
    • 类装饰器:类装饰器应用于类的定义。如果子类继承自应用了类装饰器的基类,子类不会自动继承基类的类装饰器。每个类的类装饰器独立作用于自身。
    • 方法装饰器:当子类重写基类方法并应用自己的方法装饰器时,会先执行子类方法上的装饰器,然后执行基类方法上的装饰器(如果有的话)。

TypeScript 代码示例

// 定义基类装饰器
function baseDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
        console.log('Base decorator before method execution');
        const result = originalMethod.apply(this, args);
        console.log('Base decorator after method execution');
        return result;
    };
    return descriptor;
}

// 定义子类装饰器
function subDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
        console.log('Sub decorator before method execution');
        const result = originalMethod.apply(this, args);
        console.log('Sub decorator after method execution');
        return result;
    };
    return descriptor;
}

// 定义基类
class BaseClass {
    @baseDecorator
    baseMethod() {
        console.log('Base method execution');
    }
}

// 定义子类
class SubClass extends BaseClass {
    @subDecorator
    baseMethod() {
        console.log('Sub method execution');
    }
}

// 创建子类实例并调用方法
const subInstance = new SubClass();
subInstance.baseMethod();

执行过程阐述

  1. 创建 SubClass 实例并调用 baseMethod
    • 首先遇到 @subDecorator,执行 subDecorator 函数内部逻辑。打印 Sub decorator before method execution
    • 接着执行 baseMethod 中的 console.log('Sub method execution');
    • 然后 subDecorator 函数继续执行,打印 Sub decorator after method execution
    • 之后遇到 @baseDecorator,执行 baseDecorator 函数内部逻辑。打印 Base decorator before method execution
    • 由于 SubClass 重写了 baseMethodbaseDecorator 中的 originalMethod 指向 SubClassbaseMethod 经过 subDecorator 装饰后的函数。
    • 最后 baseDecorator 函数继续执行,打印 Base decorator after method execution

整个执行结果输出为:

Sub decorator before method execution
Sub method execution
Sub decorator after method execution
Base decorator before method execution
Base decorator after method execution