在 TypeScript 中获取类方法的名称

     2023-02-22     246

关键词:

【中文标题】在 TypeScript 中获取类方法的名称【英文标题】:Get name of class method in TypeScript 【发布时间】:2016-11-02 06:08:27 【问题描述】:

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

How do I get the name of an object's type in JavaScript?Get an object's class name at runtime in TypeScript

但在某些方面有所不同。

我正在寻找属于某个类的方法的名称,并将其存储在 TypeScript/JavaScript 中的变量中。 看看下面的设置:

class Foo 

    bar()
        // logic
    


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

class ClassHelper 

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


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

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

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

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

但这失败了,因为我的方法不是以function开头的 另一个建议是:

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); 将导致传递参数,如果该方法采用一个,例如:

class Foo 

    bar(param: any)
        // logic
    



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

我已经为此苦苦挣扎了一段时间,如果有人能提供有关我如何解决此问题的任何信息,将不胜感激。

我在传入的方法上的.toString() 返回:

.toString() = "function (param)  // code "

而不是:

.toString() = "function bar(param)  // code "

根据 MDN,它也不应该这样做:

即toString对函数进行反编译,返回的字符串包括函数关键字、参数列表、大括号、函数体的来源。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString#Description

【问题讨论】:

【参考方案1】:

您好,我一直在进行一些测试,并找到了一个更简单的解决方案。

class Parent
  constructor()
    // here you initialize your stuff
  
   parentMethod1 () return "I am method 1" 
   parentMethod2 () return "I am method 2" 




class Child extends Parent
  constructor()
    // make this if you want to pass extra args to parent class
    super()
  
  childMethod1()  /*child actions*/ 
  childMethod2() /* other child actions */ 


const parent = new Parent();
const child = new Child();

console.log( Object.getOwnPropertyNames(parent.__proto__)) // --> ["constructor", "parentMethod1", "parentMethod2"]
console.log(Object.getOwnPropertyNames(child.__proto__)) //--> ["constructor", "childMethod1","childMethod2"]

console.log(parent.constructor.name) // --> Parent
console.log(child.constructor.name) // --> Child

【讨论】:

【参考方案2】:

我找到了解决方案。我不确定它的效率和可重用性如何,但它适用于多个测试用例,包括嵌套方法,例如Class -> Class -> Method

我的解决方案:

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 函数替换为常规匿名函数

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

【讨论】:

当涉及到旧浏览器和保留关键字时,此解决方案可能会有缺点,因为 lambda 可能会编译为 foo["default"]。否则看起来不错。 您可以将 lambda 函数更改为我相信的常规函数​​:function () return foo.bar; 【参考方案3】:

我采纳了 John White 的想法并对其进行了改进,使其适用于我能想到的所有情况。这种方法的优点是运行时不需要解析js代码。但是有一个极端情况,它根本无法推断出正确的属性名称,因为有多个正确的属性名称。

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】:

Object.keys 可以帮助你。 试试这个方法

class Greeter 
    test : Function;

    constructor(message: string) 

        this.test = function()
            return message;
        
        


var a = new Greeter("world");

var properties = Object.keys(a);
alert(properties.join(', ')); //test

【讨论】:

【参考方案5】:

您可以同时传入对象和方法,获取对象上的属性键数组,然后使用属性键查看每个给定属性是否与提供的方法相同的对象引用——如果是,则存在一场比赛。

class ClassHelper 
    getMethodName(obj: any, method: any) 
        var methodName: string;

        if (method) 
            Object.keys(obj).forEach(key => 
                if (obj[key] === method) 
                    methodName = key;
                
            );
        

        return methodName;
    

这有一个缺点,即主机 object 也必须是已知的。如果找不到方法,则返回undefined

【讨论】:

在尝试这种方法后,我的单元测试失败了,因此没有为我的具体情况提供合适的答案,但这是一种很好的方法,可能对其他人有用 @Colum 可能是同一个方法存在于多个属性中,还是涉及到继承?对于后者,您可以遍历原型链直到到达Object【参考方案6】:

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

在 Javascript 中,这是可行的:

Foo.prototype["bar"] // returns foo.bar <<the function>>

所以,你能想到的就是把类的原型倒过来,让类本身成为对象的key:

Foo.prototype[foo.bar] // return "bar"

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

    复杂度为O(N)(循环遍历数组) 我不确定这是否适用于所有情况。

(工作)您的问题的示例:

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"

更好的解决方案是一个 typescript 编译器选项,它可以改变 typescript 将类转换为 javascript 的方式。但是,我目前不知道有任何选项可以做这种事情。

【讨论】:

这是一个很好的解决方法,但是如果类未知,它就不起作用。这可能看起来是落后和错误的,但是在我的代码中实现这种方式的方式是,一个单独的类采用该方法的一个参数,然后它会尝试查找名称。参数可以是任何类的方法。我想我可能已经找到了解决方案,我目前正在研究它 不要忘记,当您将函数作为键放入对象时,它会转换为字符串表示形式。这使得具有相同内容的不同功能发生冲突。

如何在 TypeScript 类中正确声明计算属性名称?

】如何在TypeScript类中正确声明计算属性名称?【英文标题】:HowtoproperlydeclarecomputedpropertynamesinTypeScriptclasses?【发布时间】:2020-10-0702:49:16【问题描述】:总之如何在TypeScript中声明:在这个类中,任何以“$”开头的属性都是对... 查看详情

Typescript 从名称中获取对象属性类型

】Typescript从名称中获取对象属性类型【英文标题】:Typescriptgetobjectpropertytypefromname【发布时间】:2020-03-1709:11:10【问题描述】:我正在尝试在响应式总线类中的typescript中执行类型推断功能。这是一个例子://ThisisthefunctiongetValue&... 查看详情

在 TypeScript 中获取实例的类

】在TypeScript中获取实例的类【英文标题】:Getintance\'sclassinTypeScript【发布时间】:2018-07-0408:55:56【问题描述】:如何?这个问题类似于Getanobject\'sclassnameatruntimeinTypeScript,但我不想得到类名。我想自己上课。我需要这个做什么?... 查看详情

TypeScript 中是不是有在类中使用的关键字来获取其类型?

】TypeScript中是不是有在类中使用的关键字来获取其类型?【英文标题】:IsthereakeywordinTypeScriptusedinsideaclasstogetitstype?TypeScript中是否有在类中使用的关键字来获取其类型?【发布时间】:2020-12-2421:51:06【问题描述】:我想从类内... 查看详情

在php中获取类常量名称?

】在php中获取类常量名称?【英文标题】:Getclassconstantnamesinphp?【发布时间】:2011-02-2022:40:00【问题描述】:我有一个php类,其中包含一些指示实例状态的类常量。当我使用这个类时,在我对它运行一些方法之后,我会做一些检... 查看详情

在C ++中获取类的名称[重复]

】在C++中获取类的名称[重复]【英文标题】:GettingthenameofaclassinC++[duplicate]【发布时间】:2016-01-0413:41:12【问题描述】:在我的print方法中,我想打印我的团队类的名称(“Bar”)。有没有办法在不将其作为参数发送的情况下获取... 查看详情

在 Typescript 的静态方法中访问类类型参数的解决方法

】在Typescript的静态方法中访问类类型参数的解决方法【英文标题】:WorkaroundforaccessingclasstypeargumentsinstaticmethodinTypescript【发布时间】:2018-09-2612:47:31【问题描述】:以下错误静态成员不能引用类类型参数。以下代码的结果abstract... 查看详情

如何在javascript中获取类的私有属性名称? [复制]

】如何在javascript中获取类的私有属性名称?[复制]【英文标题】:Howtogetprivatepropertiesnamesofaclassinjavascript?[duplicate]【发布时间】:2021-10-2016:56:09【问题描述】:简介为了获取类实例的属性,我们可以使用Object.getOwnPropertyNames()方法... 查看详情

获取typescript中所有私有成员列表的方法?(代码片段)

就像标题所说,我希望能够获得一个Typescript类/实例的私有成员列表。我在测试期间尝试了这个,但我担心我会得到所有成员,并且不能在运行时判断成员是否是私有的。此外,我不确定如何对静态成员做同样的事情。typeConstruct... 查看详情

PHPUnit:从setUp()获取测试类和方法的名称?

】PHPUnit:从setUp()获取测试类和方法的名称?【英文标题】:PHPUnit:GetnameoftestclassandmethodfromsetUp()?【发布时间】:2012-09-2402:52:30【问题描述】:PHPUnit在运行特定测试之前运行测试类的setUp()方法。我为测试类中的每个测试加载... 查看详情

在 TypeScript 中使用箭头函数:如何使它们成为类方法?

】在TypeScript中使用箭头函数:如何使它们成为类方法?【英文标题】:UsingarrowfunctionsinTypeScript:howtomakethemclassmethods?【发布时间】:2012-11-3019:15:22【问题描述】:我的编程经验相当丰富,但对TypeScript还是很陌生。尝试将它与jQuery... 查看详情

java-调用get方法时获取类属性名称(代码片段)

...属性名称。我在网上看到一些东西可以使用Reflection概念获取类属性名称。我的情况:尝试编写一个方法来检查null/empty的属性值,并在属性值为null/empty时返回属性名称。例:类:publicclassMyClassprivateappName;publicvoidsetAppName(Stringapp 查看详情

java如何获取方法参数中的名称

参考技术A一、从注解中获取使用注解方式,我们需要自定义一个注解,在注解中指定参数名,然后通过反射机制,获取方法参数上的注解,从而获取到相应的注解信息。这里自定义的注解是Param,通过value参数指定参数名,定义... 查看详情

在 TypeScript 中声明动态添加的类属性

】在TypeScript中声明动态添加的类属性【英文标题】:DeclaredynamicallyaddedclasspropertiesinTypeScript【发布时间】:2017-04-2315:45:49【问题描述】:我想在不知道TypeScript中的属性名称、值和值类型的情况下将属性分配给类的实例。假设我... 查看详情

typescript中类的使用详解(代码片段)

类的简介:类中主要包含了俩个部分:属性跟方法类直接去获取实例上的方法和属性是获取不到的所以类可以通过在属性或者方法前加static来获取实例中的方法和属性属性和方法前加readonly表示只读的不可修改的classPerson/... 查看详情

TypeScript:继承类中静态方法的自引用返回类型

】TypeScript:继承类中静态方法的自引用返回类型【英文标题】:TypeScript:self-referencingreturntypeforstaticmethodsininheritingclasses【发布时间】:2015-12-0421:47:34【问题描述】:使用TypeScript1.7中的Polymorphicthis,正如我发现的here,我们可以在... 查看详情

将 AngularJS 对象作为 TypeScript 类注入(缺少方法)

】将AngularJS对象作为TypeScript类注入(缺少方法)【英文标题】:InjectAngularJSobjectasTypeScriptclass(methodsmissing)【发布时间】:2015-03-2616:27:33【问题描述】:Angular从服务中获取一些JSON作为路由解析的一部分。JSON作为Angular-ish反序列化... 查看详情

在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型

】在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型【英文标题】:InTypescripthowtogetthegenericreturntypeofamethodonaclassinstantiatedinafactory(ish)function【发布时间】:2021-10-1114:48:21【问题描述】:在下面的示例代... 查看详情