如何从该函数中获得函数名?

如何从函数内部访问函数名?

// 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();
303385 次浏览

你不能。根据标准,函数没有名字(尽管mozilla有这样一个属性)——它们只能被赋值给有名字的变量。

还有你的评论:

// access fully qualified name (ie "my.namespace.myFunc")

在函数my.namespace. myfuncc . getfn

你所能做的就是返回一个由new

所以你可以说

var obj = new my.namespace.myFunc();
console.info(obj.constructor); //my.namespace.myFunc

看这里:http://www.tek-tips.com/viewthread.cfm?qid=1209619

arguments.callee.toString();

似乎正符合你的需要。

这可能对你有用:

function foo() { bar(); }


function bar() { console.log(bar.caller.name); }

如果从匿名函数调用,运行foo()将输出“foo”或未定义。

它也适用于构造函数,在这种情况下,它将输出调用构造函数的名称(例如“Foo”)。

更多信息:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller

他们声称这是不标准的,但所有主流浏览器都支持它:Firefox、Safari、Chrome、Opera和IE。

你所做的就是将一个未命名的函数赋值给一个变量。你可能需要命名函数表达式(http://kangax.github.com/nfe/)。

var x = function x() {
console.log( arguments.callee.name );
}
x();

但我不确定这有多跨浏览器;IE6有一个问题,使你的函数名泄漏到外部作用域。同时,参数。callee已弃用,如果你使用strict mode,它会导致错误。

在ES6中,你可以只使用myFunction.name

注意:注意一些JS的迷你器可能会丢弃函数名,以更好地压缩;你可能需要调整他们的设置来避免这种情况。

在ES5中,最好的做法是:

function functionName(fun) {
var ret = fun.toString();
ret = ret.substr('function '.length);
ret = ret.substr(0, ret.indexOf('('));
return ret;
}

使用Function.caller是非标准的。在严格模式下,Function.callerarguments.callee都被禁止。

编辑:nus的基于正则表达式的答案实现了同样的事情,但有更好的性能!

你可以使用Function.name:

在大多数JavaScript实现中,一旦你在作用域中有了构造函数的引用,你就可以从它的name属性(例如Function.name,或Object.constructor.name)中获得它的字符串名称

你可以使用Function.callee:

本机arguments.caller方法已弃用,但大多数浏览器支持Function.caller,它将返回实际调用对象(其代码体): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fcaller < / >强

您可以创建一个源映射:

如果您需要的是字面函数签名("name"),而不是对象本身,你可能不得不求助于一些更定制的东西,比如创建一个你需要经常访问的API字符串值的数组引用。你可以使用Object.keys()和你的字符串数组将它们映射在一起

ES6(灵感来自下面sendy halim的回答):

myFunction.name

MDN说明。截至2015年,可以在nodejs和除IE之外的所有主流浏览器上运行。

注意:对于绑定函数,它将给出"bound <originalName>"。如果你想要得到原来的名字,你必须去掉“束缚”。


ES5(受Vlad的回答启发):

如果你有一个函数的引用,你可以这样做:

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
}
  • 我还没有对此运行单元测试,或验证实现 分歧,但原则上应该工作,如果没有留下评论
  • 注意:不适用于绑定函数
  • 注意:callercallee被认为已弃用。

[1] 我在这里包含它是因为它是合法的,而且经常有足够的语法高亮显示工具没有考虑到函数名和圆括号之间的空白。另一方面,我不知道. tostring()的任何实现会在这里包含空白,所以这就是为什么你可以省略它。


作为对最初问题的回答,我会放弃寄生继承,转而采用一些更传统的OOP设计模式。我写了一个花边新闻。OoJs来舒服地用JavaScript写OOP代码,带有一个模仿c++的功能集(还没有完成,但大部分)。

我从注释中看到,你想避免将parent需要的信息传递给它的构造函数。我必须承认,传统的设计模式并不能使您摆脱这种情况,因为使您的依赖关系明显和强制通常被认为是一件好事。

我还建议避免使用匿名函数。他们只对PITA进行调试和分析,因为一切都显示为“匿名函数”,据我所知,这对他们没有任何好处。

我也遇到过类似的问题,解决方法如下:

Function.prototype.myname = function() {
return this.toString()
.substr( 0, this.toString().indexOf( "(" ) )
.replace( "function ", "" );
}
这段代码以一种更舒适的方式实现了我已经在讨论的顶部读到的一个响应。 现在我有一个成员函数检索任何函数对象的名称。 这是完整的脚本
<script language="javascript" TYPE="text/javascript">


Function.prototype.myname = function() {
return this.toString()
.substr( 0, this.toString().indexOf( "(" ) )
.replace("function ", "" );
}
function call_this( _fn ) { document.write( _fn.myname() ); }
function _yeaaahhh() { /* do something */ }
call_this( _yeaaahhh );


</script>

这对我很管用。

function AbstractDomainClass() {
this.className = function() {
if (!this.$className) {
var className = this.constructor.toString();
className = className.substr('function '.length);
className = className.substr(0, className.indexOf('('));
this.$className = className;
}
return this.$className;
}
}

测试代码:

var obj = new AbstractDomainClass();
expect(obj.className()).toBe('AbstractDomainClass');

你可以使用name属性来获取函数名,除非你使用的是匿名函数

例如:

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());

现在让我们试试named function

var Person = function Person () {
this.someMethod = function someMethod() {};
};

现在你可以使用

// will return "someMethod"
p.getSomeMethodName()

对于支持Error的浏览器,可以使用这个选项。堆栈(可能不是全部)

function WriteSomeShitOut(){
var a = new Error().stack.match(/at (.*?) /);
console.log(a[1]);
}
WriteSomeShitOut();

当然这是针对当前函数的,但你懂的。

在你编程的时候开心地流口水

作为ECMAScript 6的一部分,你可以使用Function.name方法

function doSomething() {}


alert(doSomething.name); // alerts "doSomething"

任何constructor都公开一个属性name,即函数名。你可以通过实例(使用new)或prototype来访问constructor:

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

从正在运行的函数中获取函数名的简单方法。

.
function x(){alert(this.name)};x()

我知道这是一个老问题,但最近我为了调试目的,在尝试装饰一些React组件的方法时,也遇到了一些类似的问题。正如人们已经说过的,arguments.callerarguments.callee在严格模式下是禁止的,而在你的React编译中,这可能是默认启用的。你可以禁用它,或者我已经能够想出另一个hack,因为在React中所有的类函数都是命名的,你实际上可以这样做:

Component.prototype.componentWillMount = function componentWillMount() {
console.log('Callee name: ', this.__proto__.constructor.toString().substr(0,30));
...
}

您可以使用Error。堆栈来跟踪函数名和您在其中的确切位置。

看到stacktrace.js

这看起来是我这辈子写过的最愚蠢的东西,但很有趣: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堆栈深度。0 -返回这个函数名,1 - parent,等等 [0 + d] -只是为了理解-发生了什么;
firefoxMatch -适用于safari,但我真的有一点时间测试,因为mac的主人吸烟后回来了,并把我赶走了:'(

测试:

function limbo(){
for(let i = 0; i < 4; i++){
console.log(getName(i));
}
}
function lust(){
limbo();
}
function gluttony(){
lust();
}


gluttony();
< p > 结果:
铬:
enter image description here < / p > < p > Fitefox:
enter image description here < / p >

这个解决方案只创建只是为了好玩!不要在实际项目中使用它。它不依赖于ES规范,只依赖于浏览器实现。在下次chrome/firefox/safari更新后,它可能会被破坏。
如果d将大于堆栈长度,则没有错误(ha)处理-你将得到一个错误;
对于其他浏览器的错误消息模式-你会得到一个错误;
它必须适用于ES6类(.split('.').pop()),但你仍然可以得到一个错误;

你可以像这样使用构造函数名:

{your_function}.prototype.constructor.name

这段代码只是返回一个方法的名称。

如果我明白你想要做什么,这就是我在函数构造函数中所做的。

if (!(this instanceof arguments.callee)) {
throw "ReferenceError: " + arguments.callee.name + " is not defined";
}

这将在ES5, ES6,所有浏览器和严格模式函数中工作。

下面是使用命名函数时的样子。

(function myName() {
console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at myName (<anonymous>:2:15)

这是一个匿名函数的样子。

(() => {
console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at <anonymous>:2:15

动态检索函数名(像魔术变量一样)的一个简单解决方案是使用作用域变量。

{
function parent() {
console.log(a.name);
}; let a = parent
}
{
function child() {
console.log(a.name)
}; let a = child
};


parent();//logs parent
child();//logs child
注意:嵌套函数不再是源元素,因此不会被提升。 此外,该技术不能用于匿名函数

试试Function.name

const func1 = function() {};


const object = {
func2: function() {}
};


console.log(func1.name);
// expected output: "func1"


console.log(object.func2.name);
// expected output: "func2"