面试题答案
一键面试设计思路
- 定义装饰器函数:使用
TypeScript
的装饰器语法,定义一个函数作为装饰器,它接收一个目标对象(可以是类的原型或者函数本身)、属性名以及属性描述符。 - 记录调用参数和返回值:在装饰器函数内部,创建一个新的函数来包裹原函数,在新函数中记录参数和返回值,并调用原函数。
- 保持类型定义:通过泛型来保证被装饰函数的类型定义在静态类型检查时不丢失或出错。
- 处理类继承结构和模块导入导出:确保装饰器在不同的类继承和模块场景下都能正常工作,特别是在类型检查时。这需要正确地处理类型声明和导入导出。
代码示例
// 定义日志记录装饰器
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 ExampleClass {
@log
public exampleMethod(a: number, b: string): boolean {
return a > 0 && b.length > 0;
}
}
// 测试示例
const example = new ExampleClass();
example.exampleMethod(1, 'test');
处理复杂类继承结构和模块导入导出
假设我们有一个继承结构:
// 基类
class BaseClass {
@log
public baseMethod(): string {
return 'Base method result';
}
}
// 子类
class SubClass extends BaseClass {
@log
public subMethod(): string {
return super.baseMethod() +'from sub method';
}
}
// 模块导入导出示例
// file1.ts
export class AnotherClass {
@log
public anotherMethod(): number {
return 42;
}
}
// file2.ts
import { AnotherClass } from './file1';
const another = new AnotherClass();
another.anotherMethod();
这样,通过上述方式,在不同的类继承结构和模块导入导出场景下,日志记录装饰器都能保持对静态类型检查的兼容性和正确性。