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

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

当前回答

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

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>

其他回答

你不能。根据标准,函数没有名字(尽管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://kangax.github.com/nfe/)。

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

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

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
}

我没有对此运行单元测试,也没有对实现进行验证 分歧,但原则上应该工作,如果没有留下评论。 注意:不适用于绑定函数 注意:调用者和被调用者被认为已弃用。

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


作为对最初问题的回答,我会放弃寄生继承,转而采用一些更传统的OOP设计模式。我写了一篇花絮。OoJs可以轻松地用JavaScript编写OOP代码,并带有模仿c++的特性集(还没有完成,但大部分是)。

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

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

试试Function.name吧

const func1 = function() {};

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

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

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

这看起来是我这辈子写过的最愚蠢的东西,但很有趣: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 -父函数,等等; [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();

结果: 铬:

Fitefox:

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