面试题答案
一键面试- 编写
logMethod
泛型装饰器:
function logMethod<T extends (...args: any[]) => any>(
target: any,
propertyKey: string,
descriptor: TypedPropertyDescriptor<T>
): TypedPropertyDescriptor<T> {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling method ${propertyKey} with arguments:`, args);
const result = originalMethod.apply(this, args);
if (typeof result.then === 'function') {
return result.then((resolvedResult) => {
console.log(`Method ${propertyKey} returned:`, resolvedResult);
return resolvedResult;
});
} else {
console.log(`Method ${propertyKey} returned:`, result);
return result;
}
};
return descriptor;
}
- 定义
BaseService
类:
class BaseService {
fetchData(): string {
return 'Base data';
}
}
- 定义
ExtendedService
类并使用装饰器:
class ExtendedService extends BaseService {
@logMethod
fetchData(): { data: string, status: number } {
return { data: 'Extended data', status: 200 };
}
}
- 装饰器在类继承体系中的工作原理:
- 当在子类
ExtendedService
中使用@logMethod
装饰fetchData
方法时,装饰器实际上是对该方法的描述符进行操作。 - 它会创建一个新的函数来替换原方法,新函数在执行原方法前后添加了日志记录功能。
- 在类继承体系中,装饰器只作用于被装饰的具体方法,而不会影响父类的同名方法。子类重写的方法被装饰后,拥有了新的功能(日志记录),而父类的
fetchData
方法保持不变。
- 当在子类
- 元编程概念在此场景中的体现:
- 元编程是指程序可以对自身进行操作或生成其他程序的能力。
- 在这个场景中,
logMethod
装饰器就是一种元编程的体现。它在运行时动态地修改了类的方法行为,而不需要在方法内部直接编写日志记录代码。 - 通过装饰器,我们在类的定义之外,以一种声明式的方式为类的方法添加新功能,这改变了程序原本的行为,体现了元编程的能力。
你可以通过以下方式测试代码:
const extendedService = new ExtendedService();
extendedService.fetchData();
上述代码首先定义了一个泛型装饰器 logMethod
,该装饰器能够记录方法的参数和返回值,并且处理了异步方法的情况。然后定义了 BaseService
类及其子类 ExtendedService
,并在 ExtendedService
的 fetchData
方法上应用了 logMethod
装饰器。最后解释了装饰器在类继承体系中的工作原理以及元编程在此场景中的体现。