【问题标题】:Get method name from within a typescript method从打字稿方法中获取方法名称
【发布时间】:2018-01-26 10:31:49
【问题描述】:

我想从 Typescript 中类的实例方法中获取当前方法的名称。

(伪代码,不起作用):

class Foo {
    bar() {
        console.log(something); //what should something be?
    }
}

new Foo().bar();

我希望 'something' 返回 'bar'。我意识到this 可以给我类,我可以通过某种方式从中获取类及其属性,但我不知道如何获取“此函数”(即方法栏,而不是类 Foo)。

我见过其他几个与查找类名等相关的问题,但没有一个涉及获取当前方法名的问题。

【问题讨论】:

  • 为什么需要知道方法的名称?你打电话给它是为了知道它的名字。
  • 这不是一个真正的打字稿问题... :)
  • @Rienk - 我正在尝试做一些更复杂的事情(特别是打字稿中 ruby​​ 的 method_missing 行为),但作为一个更简单的例子,假设我有带有(大量方法)的遗留代码,如 @ 987654325@ 和getBar(),我想使用getObject(objName) 函数来处理所有这些,该函数解析函数名称,并按名称从字典中返回对象。我想在每个这样的函数中调用 getObject(thisFuncName) 而不必更改每个这样的函数来说出 getObject('foo') 等内容。
  • Anand:然后用您想要使用 TypeScript 实现的模式打开一个新问题。我认为这样会更好。正如@Kokodoko 所说,这不是 TypeScript,而是 JavaScript。
  • arguments.callee.name,但是在严格模式下不起作用,类方法在严格模式下执行。您可以尝试使用Proxy,但并非所有浏览器都支持代理..

标签: javascript typescript


【解决方案1】:

除了arguments.callee.name,没有直接的方法可以得到这个。

我提出了另外两种方法:

使用装饰器注入方法名:

function annotateName(target, name, desc) {
    var method = desc.value;
    desc.value = function () {
        var prevMethod = this.currentMethod;
        this.currentMethod = name;
        method.apply(this, arguments);
        this.currentMethod = prevMethod;   
    }
}

class Foo {
    currentMethod: string;

    @annotateName
    bar() {
        alert(this.currentMethod);
        this.tux();
        alert(this.currentMethod);
    }

    @annotateName
    tux() {
        alert(this.currentMethod);
    }
}

new Foo().bar();

缺点是您必须注释所有要从中获取名称的函数。相反,您可以只对类进行注释,然后在装饰器中迭代所有原型函数并应用相同的想法。


我的第二个选项没有标准化,需要更加小心才能在浏览器中获得一致的结果。它依赖于创建一个错误对象并获取它的stack 跟踪。

class Foo {
    bar() {
        console.log(getMethodName());    
    }
}

function getMethodName() {
    var err = new Error();
    return /at \w+\.(\w+)/.exec(err.stack.split('\n')[2])[1] // we want the 2nd method in the call stack

}

new Foo().bar();

【讨论】:

【解决方案2】:

不确定这是否有帮助,但是:

class Foo {
    bar() {
        console.log(Object.getOwnPropertyNames(Foo.prototype)); // ["constructor", "bar"]
    }
}

new Foo().bar();

【讨论】:

    【解决方案3】:

    类名 - Foo.name 方法名称 - this.bar.name

    【讨论】:

    • 问题是关于如何获取 current-executing 方法的名称。
    【解决方案4】:

    请记住,在编译和缩小期间,您可能会丢失您尝试使用的实际名称。您可能会考虑查看 ts-nameof babel 宏,它在编译期间读取几乎任何东西的名称并返回它的实际字符串表示形式。

    【讨论】:

      【解决方案5】:

      只是用另一个有趣的观点来回答这个问题,你可以做(​​但不应该做)这样的事情:

      class Foo {
          constructor(private http: HttpClient) {
      
              const apiUrl = 'http://myapi.com/api/';
      
              {
                  const functionName = 'getBar';
                  this[functionName] = function () {
                      return http.get(apiUrl + functionName);
                  }
              }
      
              {
                  const functionName = 'postBar';
                  this[functionName] = function () {
                      return http.get(apiUrl + functionName);
                  }
              }
      
              {
                  const functionName= 'putBar';
                  this[functionName] = function () {
                      return http.get(apiUrl + functionName);
                  }
              }
      
              {
                  const functionName= 'deleteBar';
                  this[functionName] = function () {
                      return http.get(apiUrl + functionName);
                  }
              }
          }
      }
      

      这当然不是一个优雅的解决方案,我真的无法想象一个好的用例来做这样的事情,因为我很确定编译器无法识别new Foo(http).deleteBar()。也许有人可以用这个想法想出一个优雅的解决方案,我会把它留给别人做实验。

      但是使用这种模式(如果您使用某种 devops 脚手架或“强大的复制粘贴技能”),您始终可以通过 functionName 访问您的方法的名称

      【讨论】:

        【解决方案6】:

        我也在寻找解决方案,试试这个:

        class Foo {
          bar() {
              console.log(this.bar.name); // <-- Print out the function name.
          }
        }
          
        new Foo().bar(); 
        

        很好的是,如果您更改函数名称,则会收到错误,但忘记更新控制台语句。

        【讨论】:

        • this.bar.name 比只输入bar 更长。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-27
        • 2022-11-03
        相关资源
        最近更新 更多