TypeScript方法装饰器问题:如何存储可调用方法并关联参数?
问题原因
你当前的错误是因为装饰实例方法时,target参数对应的是类的原型对象(比如Bar.prototype),而不是被装饰的方法本身。你把原型对象存入了cachedMethods,自然调用时会提示“不是函数”。
解决方案
要获取被装饰的方法,应该从装饰器参数里的descriptor.value属性读取——这才是方法的实际实现函数。同时需要注意实例方法的this指向问题:直接调用缓存的方法会导致this丢失,需要根据需求处理绑定。
修正后的代码
class Foo { static cachedMethods: Map<string, (arg: string) => void> = new Map(); static decorator = (decoratorArg: string) => ( target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<(arg: string) => void> ): void => { // 从descriptor.value提取实际的方法函数 const method = descriptor.value; if (method) { Foo.cachedMethods.set(decoratorArg, method); } }; } class Bar { @Foo.decorator("some data") method1(arg: string) { console.log(arg); // 如果方法用到this,比如console.log(this); 直接调用缓存方法时this会是undefined } @Foo.decorator("some other data") method2(arg: string) { console.log(arg); } } // 调用示例 const barInstance = new Bar(); const func = Foo.cachedMethods.get("some data")!; // 情况1:方法内部未使用this,直接调用即可 func("hello world"); // 情况2:方法内部依赖this,需要绑定实例 func.bind(barInstance)("hello world with correct this");
补充说明
- 如果装饰的是静态方法,
target参数会是类本身(比如Bar),此时descriptor.value是静态方法,调用时无需绑定实例,直接调用即可。 - 如果希望在装饰器阶段就固定
this指向原型,可以修改为method.bind(target)存入缓存,但这样所有实例会共用同一个绑定上下文,适合无状态的方法。
内容的提问来源于stack exchange,提问作者Ben Schreiber
相关产品推荐
相关产品推荐

