首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在TypeScript中获取类的名称

在TypeScript中获取类的名称
EN

Stack Overflow用户
提问于 2016-06-30 08:46:48
回答 6查看 17.6K关注 0票数 10

对于任何查看此问题的人,此问题类似于以下内容:

如何在JavaScript中获取对象类型的名称?

在运行时在TypeScript中获取对象的类名

然而,这在几个方面是不同的。

我希望获得属于类的方法的名称,并将其存储在TypeScript / JavaScript中的变量中。

请查看以下设置:

代码语言:javascript
运行
复制
class Foo {

    bar(){
        // logic
    }

}

以上是有效的TypeScript,我希望在另一个类中创建一个方法,该方法将返回bar()方法的名称,即"bar"

例:

代码语言:javascript
运行
复制
class ClassHelper {

    getMethodName(method: any){
        return method.name; // per say
    }

}

然后,我希望能够以以下方式使用ClassHelper

代码语言:javascript
运行
复制
var foo = new Foo();
var barName = ClassHelper.getMethodName(foo.bar); // "bar"

我看过很多帖子,有些建议使用以下内容:

代码语言:javascript
运行
复制
var funcNameRegex = /function (.{1,})\(/;   
var results = (funcNameRegex).exec(obj.toString());
var result = results && results.length > 1 && results[1];

但是这失败了,因为我的方法不是以function开头的

另一项建议是:

代码语言:javascript
运行
复制
public getClassName() {
    var funcNameRegex = /function (.{1,})\(/;
    var results  = (funcNameRegex).exec(this["constructor"].toString());
    return (results && results.length > 1) ? results[1] : "";
}

然而,这只会返回类名,并且从阅读帖子中可以看出,使用constructor似乎是不可靠的。

此外,当我使用其中一些方法调试代码时,传入如下所示的方法:ClassHelper.getMethodName(foo.bar);将导致参数被传递,如果该方法采用一个方法,例如:

代码语言:javascript
运行
复制
class Foo {

    bar(param: any){
        // logic
    }

}

var foo = new Foo();
var barName = ClassHelper.getMethodName(foo.bar); // results in param getting passed through

我已经为这个问题挣扎了一段时间,如果有人知道我如何解决这个问题,我将不胜感激。

传入的方法上的.toString()返回以下内容:

代码语言:javascript
运行
复制
.toString() = "function (param) { // code }"

而不是:

代码语言:javascript
运行
复制
.toString() = "function bar(param) { // code }"

根据MDN的说法,它也不应该:

也就是说,toString对函数进行解压缩,返回的字符串包括函数关键字、参数列表、大括号和函数体的源。 对象/函数/toString#描述

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2016-06-30 11:14:08

我找到了解决办法。我不确定它的效率和可重用性,但是它在多个测试用例中工作,包括嵌套的方法,例如Class -> Class -> Method

我的解决方案:

代码语言:javascript
运行
复制
class ClassHelpers {
    getName(obj: any): string {    
        if (obj.name) {
            return obj.name;
        }

        var funcNameRegex = /function (.{1,})\(/;   
        var results = (funcNameRegex).exec(obj.toString());
        var result = results && results.length > 1 && results[1];

        if(!result){
            funcNameRegex = /return .([^;]+)/;
            results = (funcNameRegex).exec(obj.toString());
            result = results && results.length > 1 && results[1].split(".").pop();
        }

        return result || "";
    }
}


class Foo {

    bar(param: any){
        // logic
    }

}

var foo = new Foo();
var barName = ClassHelper.getMethodName(() => foo.bar);

lambda表示法ClassHelper.getMethodName(() => foo.bar);是使其工作的关键,因为它允许.toString()包含return foo.bar;

接下来,我必须从.toString()中提取方法调用,然后使用数组和字符串函数返回最后一个子字符串,这不可避免地是方法名。

就像我说的,它可能不是最优雅的解决方案,但它已经成功,甚至适用于嵌套方法。

注意:您可以用常规匿名函数替换lambda函数。

代码语言:javascript
运行
复制
var foo = new Foo();
var barName = ClassHelper.getMethodName(function() { return foo.bar; });
票数 3
EN

Stack Overflow用户

发布于 2016-06-30 12:01:59

我采纳了约翰·怀特的想法,并对其进行了改进,使之适用于我所能想到的每一种情况。该方法的优点是不需要在运行时解析js代码。但是有一种边缘情况,即它无法推断出正确的属性名,因为有多个正确的属性名称。

代码语言:javascript
运行
复制
class Foo {
  bar() {}
  foo() {}
}

class ClassHelper {
  static getMethodName(obj, method) {
    var methodName = null;
    Object.getOwnPropertyNames(obj).forEach(prop => {
      if (obj[prop] === method) {
        methodName = prop;
      }
    });

    if (methodName !== null) {
      return methodName;
    }
    
    var proto = Object.getPrototypeOf(obj);
    if (proto) {
      return ClassHelper.getMethodName(proto, method);
    }
    return null;
  }
}

var foo = new Foo();
console.log(ClassHelper.getMethodName(foo, foo.bar));
console.log(ClassHelper.getMethodName(Foo.prototype, foo.bar));
console.log(ClassHelper.getMethodName(Foo.prototype, Foo.prototype.bar));

var edgeCase = { bar(){}, foo(){} };
edgeCase.foo = edgeCase.bar;
console.log(ClassHelper.getMethodName(edgeCase, edgeCase.bar));

票数 4
EN

Stack Overflow用户

发布于 2016-06-30 09:42:41

不幸的是,在编译到JS (正如您正确推断的那样)时,类型记录类方法的名称丢失了。通过将类型记录方法添加到Javascript类的原型中,将其编译为Javascript。(有关更多信息,请查看编译后的Javascript )。

在Javascript中,这项工作是:

代码语言:javascript
运行
复制
Foo.prototype["bar"] // returns foo.bar <<the function>>

因此,您可以想到的是反转类的原型,因此类本身成为对象的关键:

代码语言:javascript
运行
复制
Foo.prototype[foo.bar] // return "bar"

当然,这是一个非常麻烦的解决方案,因为

  1. 复杂性是O(N) (通过数组循环)
  2. 我不确定这在每一种情况下都有效。

(工作)你的问题的例子:

代码语言:javascript
运行
复制
class Foo{
    bar(){}
}

class ClassHelper{
    static reversePrototype(cls:any){
        let r = {};
        for (var key in cls.prototype){
            r[cls.prototype[key]] = key;
        }
        return r;
    }

    static getMethodNameOf(cls: any, method:any):string{
        let reverseObject = ClassHelper.reversePrototype(cls);
        return reverseObject[method];
    }
}

var foo = new Foo();
console.log(ClassHelper.getMethodNameOf(Foo, foo.bar)) // "bar"

更好的解决方案是一个类型记录编译器选项,它将类型转录文件类的方式更改为javascript。但是,我目前还不知道有什么办法可以做这种事情。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38118137

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档