Javascript 如何从该函数中获取函数名称?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2648293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the function name from within that function?
提问by Scott Klarenbach
How can I access a function name from inside that function?
如何从该函数内部访问函数名称?
// parasitic inheritance
var ns.parent.child = function() {
var parent = new ns.parent();
parent.newFunc = function() {
}
return parent;
}
var ns.parent = function() {
// at this point, i want to know who the child is that called the parent
// ie
}
var obj = new ns.parent.child();
回答by Vlad A Ionescu
In ES5, the best thing to do is:
在 ES5 中,最好的做法是:
function functionName(fun) {
var ret = fun.toString();
ret = ret.substr('function '.length);
ret = ret.substr(0, ret.indexOf('('));
return ret;
}
Using Function.calleris non-standard. Function.callerand arguments.calleeare both forbidden in strict mode.
使用Function.caller是非标准的。Function.caller并且arguments.callee在严格模式下都被禁止。
Edit: nus's regex based answer below achieves the same thing, but has better performance!
编辑:下面基于 nus 正则表达式的答案实现了相同的目的,但性能更好!
In ES6, you can just use myFunction.name.
在 ES6 中,你可以只使用myFunction.name.
Note: Beware that some JS minifiers might throw away function names, to compress better; you may need to tweak their settings to avoid that.
注意:请注意,某些 JS 压缩器可能会丢弃函数名称,以便更好地压缩;您可能需要调整他们的设置以避免这种情况。
回答by Vlad A Ionescu
ES6(inspired by sendy halim's answer below):
ES6(灵感来自sendy halim在下面的回答):
myFunction.name
Explanation on MDN. As of 2015 works in nodejs and all major browsers except IE.
MDN 上的说明。截至 2015 年,适用于 nodejs 和除 IE 之外的所有主要浏览器。
Note: On bound functions this will give "bound <originalName>". You will have to strip the "bound " if you want to get the original name.
注意:在绑定函数上,这将给出“ bound <originalName>”。如果您想获得原始名称,则必须去除“绑定”。
ES5(inspired by Vlad's answer):
ES5(受弗拉德的回答启发):
If you have a reference to the function, you can do:
如果您有对该函数的引用,则可以执行以下操作:
function functionName( func )
{
// Match:
// - ^ the beginning of the string
// - function the word 'function'
// - \s+ at least some white space
// - ([\w$]+) capture one or more valid JavaScript identifier characters
// - \s* optionally followed by white space (in theory there won't be any here,
// so if performance is an issue this can be omitted[1]
// - \( followed by an opening brace
//
var result = /^function\s+([\w$]+)\s*\(/.exec( func.toString() )
return result ? result[ 1 ] : '' // for an anonymous function there won't be a match
}
- I have not run unit tests on this, or verified implementation differences, but in principle it should work, if not leave a comment.
- Note: won't work on bound functions
- Note: that
callerandcalleeare considered deprecated.
- 我没有对此运行单元测试,也没有验证实现差异,但原则上它应该可以工作,如果没有发表评论。
- 注意:不适用于绑定函数
- 注意: that
caller和callee被视为已弃用。
[1]I include it here because it is legal and often enough syntax highlighting tools fail to take into account the white space between function name and parenthesis. On the other hand, I'm not aware of any implementation of .toString() that will include white space here, so that's why you can omit it.
[1]我把它包含在这里是因为它是合法的,而且语法高亮工具通常没有考虑到函数名和括号之间的空格。另一方面,我不知道 .toString() 的任何实现会在此处包含空格,因此您可以省略它。
As an answer to the original question, I would drop parasitic inheritance and go for some more traditional OOP design patterns. I wrote a TidBits.OoJsto comfortably write OOP code in JavaScript with a feature set mimicking C++ (not yet complete, but mostly).
作为对原始问题的回答,我将放弃寄生继承并采用一些更传统的 OOP 设计模式。我写了一个TidBits.OoJs来舒适地用 JavaScript 编写 OOP 代码,其中包含模仿 C++ 的功能集(尚未完成,但主要是)。
I see from the comments that you would like to avoid passing information parentneeds to it's constructor. I must admit that traditional design patterns won't save you from that one though, since it is generally a considered a good thing to make your dependencies obvious and enforced.
我从评论中看到您希望避免将信息parent需求传递给它的构造函数。我必须承认,传统的设计模式不会让您免于这种情况,因为通常认为使您的依赖项显而易见并强制执行是一件好事。
I would also suggest to steer away from anonymous functions. They only make debugging and profiling a PITA because everything just shows up as "anonymous function", and there is no benefit to them that I'm aware of.
我还建议避免使用匿名函数。他们只对 PITA 进行调试和分析,因为一切都只是显示为“匿名函数”,据我所知,他们没有任何好处。
回答by wildcard
what you're doing is assigning unnamed function to a variable. you probably need named function expression instead ( http://kangax.github.com/nfe/).
您正在做的是将未命名的函数分配给变量。您可能需要命名函数表达式(http://kangax.github.com/nfe/)。
var x = function x() {
console.log( arguments.callee.name );
}
x();
however I'm not sure how much cross-browser that is; there's an issue with IE6 that makes you function's name leak to the outer scope. also, arguments.callee is kind of deprecated and will result in error if you're using strict mode.
但是我不确定那是多少跨浏览器;IE6 存在一个问题,使您的函数名称泄漏到外部作用域。此外,arguments.callee 有点过时,如果您使用 .callee 会导致错误strict mode。
回答by roland
Any constructorexposes a property name, which is the function name. You access the constructorvia an instance (using new) or a prototype:
Anyconstructor公开一个属性name,即函数名称。您可以constructor通过实例(使用new)或 a 访问prototype:
function Person() {
console.log(this.constructor.name); //Person
}
var p = new Person();
console.log(p.constructor.name); //Person
console.log(Person.prototype.constructor.name); //Person
回答by user3335966
It looks like the most stupid thing, that I wrote in my life, but it's funny :D
这看起来是我一生中写的最愚蠢的事情,但很有趣:D
function getName(d){
const error = new Error();
const firefoxMatch = (error.stack.split('\n')[0 + d].match(/^.*(?=@)/) || [])[0];
const chromeMatch = ((((error.stack.split('at ') || [])[1 + d] || '').match(/(^|\.| <| )(.*[^(<])( \()/) || [])[2] || '').split('.').pop();
const safariMatch = error.stack.split('\n')[0 + d];
// firefoxMatch ? console.log('firefoxMatch', firefoxMatch) : void 0;
// chromeMatch ? console.log('chromeMatch', chromeMatch) : void 0;
// safariMatch ? console.log('safariMatch', safariMatch) : void 0;
return firefoxMatch || chromeMatch || safariMatch;
}
d- depth of stack. 0- return this function name, 1- parent, etc.;[0 + d]- just for understanding - what happens;firefoxMatch- works for safari, but I had really a little time for testing, because mac's owner had returned after smoking, and drove me away :'(
d- 堆栈深度。0- 返回这个函数名,1- 父级等;[0 + d]- 只是为了理解 - 会发生什么;firefoxMatch- 为 safari 工作,但我真的有一点时间来测试,因为 mac 的主人在吸烟后回来了,把我赶走了 :'(
Testing:
测试:
function limbo(){
for(let i = 0; i < 4; i++){
console.log(getName(i));
}
}
function lust(){
limbo();
}
function gluttony(){
lust();
}
gluttony();
This solution was creating only just for fun! Dont use it for real projects. It not depends on ES specification, it depends only on browser realisation. After next chrome/firefox/safari update it may be broken.
More than that there is no error (ha) processing - if dwill be more than stack length - you will get an error;
For other wrowsers error's messaage pattern - you will get an error;
It must work for ES6 classes (.split('.').pop()), but you sill can get an erorr;
这个解决方案只是为了好玩!不要将它用于实际项目。它不取决于 ES 规范,它只取决于浏览器实现。在下一次 chrome/firefox/safari 更新后,它可能会损坏。
不仅如此,没有错误(ha)处理 - 如果d超过堆栈长度 - 你会得到一个错误;
对于其他浏览器错误的消息模式 - 你会得到一个错误;
它必须适用于 ES6 类 ( .split('.').pop()),但您可能会遇到错误;
回答by Jacob Mouka
This might work for you:
这可能对你有用:
function foo() { bar(); }
function bar() { console.log(bar.caller.name); }
running foo() will output "foo" or undefined if you call from an anonymous function.
如果从匿名函数调用,运行 foo() 将输出“foo”或 undefined。
It works with constructors too, in which case it would output the name of the calling constructor (eg "Foo").
它也适用于构造函数,在这种情况下,它将输出调用构造函数的名称(例如“Foo”)。
More info here: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller
更多信息在这里:https: //developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller
They claim it's non-standard, but also that it's supported by all major browsers: Firefox, Safari, Chrome, Opera and IE.
他们声称它是非标准的,但所有主要浏览器都支持它:Firefox、Safari、Chrome、Opera 和 IE。
回答by plodder
You can't. Functions don't have names according to the standard (though mozilla has such an attribute) - they can only be assigned to variables with names.
你不能。根据标准,函数没有名称(尽管 mozilla 有这样的属性)——它们只能分配给具有名称的变量。
Also your comment:
还有你的评论:
// access fully qualified name (ie "my.namespace.myFunc")
is inside the function my.namespace.myFunc.getFn
在函数 my.namespace.myFunc.getFn 内
What you can do is return the constructor of an object created by new
您可以做的是返回由 new 创建的对象的构造函数
So you could say
所以你可以说
var obj = new my.namespace.myFunc();
console.info(obj.constructor); //my.namespace.myFunc
回答by no_ripcord
You could use this, for browsers that support Error.stack (not nearly all, probably)
对于支持 Error.stack 的浏览器,您可以使用它(可能不是几乎所有)
function WriteSomeShitOut(){
var a = new Error().stack.match(/at (.*?) /);
console.log(a[1]);
}
WriteSomeShitOut();
of course this is for the current function, but you get the idea.
当然,这是针对当前功能的,但您明白了。
happy drooling while you code
编码时快乐流口水
回答by muhamad zolfaghari
You can use constructor name like:
您可以使用构造函数名称,如:
{your_function}.prototype.constructor.name
this code simply return name of a method.
此代码仅返回方法的名称。
回答by sendy halim
You can use nameproperty to get the function name, unless you're using an anonymous function
您可以使用name属性来获取函数名称,除非您使用匿名函数
For example:
例如:
var Person = function Person () {
this.someMethod = function () {};
};
Person.prototype.getSomeMethodName = function () {
return this.someMethod.name;
};
var p = new Person();
// will return "", because someMethod is assigned with anonymous function
console.log(p.getSomeMethodName());
now let's try with named function
现在让我们尝试命名函数
var Person = function Person () {
this.someMethod = function someMethod() {};
};
now you can use
现在你可以使用
// will return "someMethod"
p.getSomeMethodName()


