对于任何查看此问题的人,此问题类似于以下内容:
然而,这在几个方面是不同的。
我希望获得属于类的方法的名称,并将其存储在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对函数进行解压缩,返回的字符串包括函数关键字、参数列表、大括号和函数体的源。 对象/函数/toString#描述
发布于 2016-06-30 11:14:08
我找到了解决办法。我不确定它的效率和可重用性,但是它在多个测试用例中工作,包括嵌套的方法,例如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; });
发布于 2016-06-30 12:01:59
我采纳了约翰·怀特的想法,并对其进行了改进,使之适用于我所能想到的每一种情况。该方法的优点是不需要在运行时解析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));
发布于 2016-06-30 09:42:41
不幸的是,在编译到JS (正如您正确推断的那样)时,类型记录类方法的名称丢失了。通过将类型记录方法添加到Javascript类的原型中,将其编译为Javascript。(有关更多信息,请查看编译后的Javascript )。
在Javascript中,这项工作是:
Foo.prototype["bar"] // returns foo.bar <<the function>>
因此,您可以想到的是反转类的原型,因此类本身成为对象的关键:
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"
更好的解决方案是一个类型记录编译器选项,它将类型转录文件类的方式更改为javascript。但是,我目前还不知道有什么办法可以做这种事情。
https://stackoverflow.com/questions/38118137
复制相似问题