推荐答案
// www.javascriptcn.com code example
function cache(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const cacheMap = new Map();
descriptor.value = function(...args: any[]) {
const cacheKey = JSON.stringify(args);
if (cacheMap.has(cacheKey)) {
return cacheMap.get(cacheKey);
}
const result = originalMethod.apply(this, args);
cacheMap.set(cacheKey, result);
return result;
};
return descriptor;
}
class MyClass {
@cache
expensiveOperation(input: number): number {
console.log('Calculating...');
return input * 2;
}
}
const instance = new MyClass();
console.log(instance.expensiveOperation(5)); // Calculating... 10
console.log(instance.expensiveOperation(5)); // 10 (from cache)本题详细解读
装饰器的作用
装饰器是一种特殊类型的声明,它可以被附加到类声明、方法、访问器、属性或参数上。装饰器使用 @expression 的形式,其中 expression 必须是一个函数,它会在运行时被调用,传入相关的装饰器信息。
缓存装饰器的实现
装饰器函数定义:
cache是一个方法装饰器,它接收三个参数:target:装饰器所修饰的类的原型对象。propertyKey:被修饰的方法的名称。descriptor:被修饰方法的属性描述符。
缓存逻辑:
- 在装饰器内部,我们首先保存了原始方法的引用
originalMethod。 - 然后创建了一个
Map对象cacheMap用于存储缓存结果。 - 在装饰器返回的新方法中,我们首先将传入的参数序列化为字符串作为缓存的键
cacheKey。 - 如果
cacheMap中已经存在这个键,则直接返回缓存的结果。 - 如果缓存中没有这个键,则调用原始方法,并将结果存入
cacheMap中,最后返回结果。
- 在装饰器内部,我们首先保存了原始方法的引用
应用装饰器:
- 在
MyClass类中,我们使用@cache装饰器来修饰expensiveOperation方法。 - 当调用
expensiveOperation方法时,装饰器会自动处理缓存逻辑,避免重复计算。
- 在
使用场景
这种缓存装饰器非常适合用于那些计算成本较高、但输入参数相对固定的方法。通过缓存结果,可以显著提高性能,特别是在频繁调用相同参数的场景下。