面试题答案
一键面试- 定义日志切面装饰器:
- 使用属性装饰器,在装饰器内部通过
Reflect
API来存储和获取属性相关信息。 - 定义一个
LogAspect
装饰器,接收一个参数message
用于日志记录的描述。
- 使用属性装饰器,在装饰器内部通过
function LogAspect(message: string) {
return function (target: any, propertyKey: string) {
let value: any;
const descriptor: PropertyDescriptor = {
get() {
const operationTime = new Date().toISOString();
const operationType = 'get';
const preValue = value;
const postValue = value;
console.log(`${operationTime} - ${operationType} - ${message} - preValue: ${preValue}, postValue: ${postValue}`);
return value;
},
set(newValue: any) {
const operationTime = new Date().toISOString();
const operationType ='set';
const preValue = value;
value = newValue;
const postValue = value;
console.log(`${operationTime} - ${operationType} - ${message} - preValue: ${preValue}, postValue: ${postValue}`);
}
};
return descriptor;
};
}
- 在类中使用装饰器:
- 创建一个类,为类的属性应用
LogAspect
装饰器。
- 创建一个类,为类的属性应用
class ExampleClass {
@LogAspect('Example property operation')
exampleProperty: string;
constructor() {
this.exampleProperty = 'initial value';
}
}
- 测试代码:
- 创建类的实例,并访问和修改属性,观察日志输出。
const example = new ExampleClass();
console.log(example.exampleProperty);
example.exampleProperty = 'new value';
通过上述步骤,我们利用TypeScript的属性装饰器实现了一个日志切面,它可以灵活应用于不同类的多个属性上,并且对业务代码的侵入性较小。通过元编程技术(这里主要是Reflect
API的使用),我们能够在不改变属性原有逻辑太多的情况下,添加日志记录功能。