JavaScript: 如何在函数内获取函数名

5

是的,我认识到关于这个问题的帖子已经数不胜数了,首先有:

从函数本身获取函数名称[重复]

从函数内部获取函数名称

arguments.callee已被弃用 - 应该使用什么代替?

但是给出的答案的问题在于arguments.callee已被弃用。所有答案都说只需要给函数命名即可。然而,据我所知,这并不能解决我的问题。假设我有以下函数:

function blah() {
  // arguments.callee.name is deprecated
  console.log('The function name is: ' + arguments.callee.name + '.');
}

但是因为它已经被弃用,我不应该再使用它,那么我应该使用什么替代品呢?当我在函数内部时,有没有办法访问函数名称,或者我只是徒劳无功?

如果这可以简化事情,我正在使用Ext JS框架,但我还没有找到一种知道函数名称的方法。如果没有,是否有jQuery方法?我很绝望。


1
有没有情况下你不能硬编码函数名?我同意能够以编程方式获取它会很好,但这是必要的吗? - Raekye
是的,我正在尝试创建某种日志记录机制,并且我不想使用设置名称来调用日志记录机制...我只希望它知道名称。这样做更有意义,因为它是动态的。如果函数名称更改,我可能会忘记为记录器进行更改。 - incutonez
2
可能更容易查看现代浏览器中提供的一些堆栈跟踪可见性机制。它们不是相互兼容的,但这可能会更清晰,因为您不必显式地传递任何内容。 - Pointy
1
是的,在发布这个问题之前,我看过整个堆栈跟踪方法,但它似乎太过繁琐了。我不明白为什么这么简单的事情基本上是不可能的。 - incutonez
2个回答

2

您可以触发异常并查看堆栈跟踪。

以下上下文证明适用于Chrome浏览器:

function test () {
  try { [].undef () } catch (e) {
     console.log (e.stack.split ('\n')[1].split (/\s+/)[2]);
  }
}

如果需要更加稳健的实现,请参考http://www.eriwen.com/javascript/js-stack-trace/,该网站提供了在任何浏览器中完整的堆栈跟踪。

更现代和全面的堆栈跟踪分析器是http://stacktracejs.com


有趣。我确实看到了 Stack Trace 库……这可能是我现在唯一的选择。让我感到困惑的是,这为什么如此困难。 - incutonez
这就是 JavaScript 呀! :-) - sherb
1
可怜的JavaScript...它只是试图从孩子成长为成年人,但不幸的是它卡在了叛逆的青少年阶段。 - incutonez
@HBP,谢谢你的想法,顺便说一下...那就是我回答的原因。 - incutonez
这绝对是我迄今为止见过的最有趣的方法。 - deepfritz
显示剩余2条评论

0

经过一番探索,我找到了这个SO线程,在此基础上,我制作了一个非常非常hacky的解决方案(在Chrome和FF中都可以工作...不确定IE是否可以,但我怀疑它能否正常工作)。警告:这对我的特定用途非常有效,但您的效果肯定会有所不同。无论如何,这是我的代码:

getLogLocation: function() {
  var ua = navigator.userAgent;
  var isFF = ua.search(/firefox/i) !== -1 ? true : false;
  var isChrome = ua.search(/chrome/i) !== -1 ? true : false;
  if (isFF || isChrome) {
    var stack = Error().stack,
        cname = '',
        funcPattern,
        classPattern = /.*\/(.*)\.js/;  // looking for something between the last backslash and .js
    if (stack) {
      var stacks = stack.split('\n');
      if (stacks) {
        var theStack;
        // the browsers create the stack string differently
        if (isChrome) {
          // the stack has getClassName, then logMessage, then our calling class, but Chrome has some added garbage
          theStack = stacks[4];
          funcPattern = /.*\.(.*)\s+\(/;   // looking for something between a period and the first paren
        }
        else {
          theStack = stacks[2];
          funcPattern = /^\.*(.*)\@/;  // looking for something between a period and an @ symbol
        }
        var matches = theStack.match(classPattern);
        cname = matches[1] + '::';
        matches = theStack.match(funcPattern);
        cname += matches[1] + ':';
      }
    }
    return cname;
  }
}

如果你好奇我的技术栈是什么样子的,这里是相关的代码:

Firefox(省略了很多行)

".getClassName@http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836090216:72
.logMessage@http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836090216:31
.constructor@http://127.0.0.1/javascripts/app/BaseController.js?_dc=1383836089659:39
..."

Chrome(前两行是我必须适应的垃圾...之后,它类似于FF的堆栈字符串)

"Error
    at Error (<anonymous>)
    at Ext.define.getLogLocation (http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836606405:72:19)
    at Ext.define.logMessage (http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836606405:31:24)
    at new Ext.define.constructor (http://127.0.0.1/javascripts/app/BaseController.js?_dc=1383836606265:39:14)
    ..."

请参见this jsFiddle以获取一个可工作的示例...由于我们不再使用Ext JS,所以必须更改堆栈值。

现在,稍微解释一下。 getLogLocation 作为一个函数存在于 Ext JS 类中 (ConsoleMixin),另一个函数在 ConsoleMixin 中 (logMessage) 调用 getLogLocation,并且 logMessage 被我们外部类的函数 (constructor) 调用,这就是为什么我必须补偿前两个堆栈值的原因。像我说的那样,非常 hacky 并且特定于我的需求,但希望有人能够利用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接