You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:39:28