【问题标题】:JavaScript: Get function name inside of itselfJavaScript:在自身内部获取函数名称
【发布时间】:2013-10-30 09:48:20
【问题描述】:

是的,我知道关于这个问题有无数的线索,对于初学者来说:

Get function name from function itself [duplicate]

Get function name from inside itself

Arguments.callee is deprecated - what should be used instead?

但是给出的答案的问题是arguments.callee is deprecated。所有的答案都说只是给你的函数一个名字。但是,据我所知,这并不能解决我的问题。假设我有以下功能:

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

但是因为它已被弃用,我不应该使用它,那么我应该使用什么来代替呢?有什么方法可以在函数本身内部访问函数名称,还是我只是在这里失去了可能性?

如果它使事情变得更容易,我正在使用框架 Ext JS,但我还没有找到知道函数名称的方法。如果没有,是否有 jQuery 方法?我在这里很绝望。

【问题讨论】:

  • 有没有不能硬编码函数名的情况?我同意能够以编程方式获取它会很好,但有必要吗?
  • 嗯,是的。我正在尝试创建某种日志记录机制,并且我不想使用设置名称调用日志记录机制......我只是希望它知道名称。这样做更有意义,因为它是动态的。如果函数名称更改,我可能会忘记为记录器更改它。
  • 查看现代浏览器中可用的一些堆栈跟踪可见性机制可能会更容易。它们不是相互兼容的,但它可能会更简洁,因为您不必显式传入 anything
  • 是的,我在发布这个问题之前看到了整个堆栈跟踪方法,但这似乎有点矫枉过正。我不明白为什么这么简单的事情基本上是不可能的。

标签: javascript jquery extjs arguments


【解决方案1】:

经过一番探索,我想出了this SO thread,因此在此基础上,我制作了一个非常非常实用的解决方案(在 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) 调用,这就是为什么我必须补偿前 2 个堆栈值。就像我说的,非常 hacky 并且特定于我的需要,但希望有人可以使用它。

【讨论】:

    【解决方案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 库……这可能是我目前唯一的选择。让我感到困惑,这太难了。
    • 这是给你的Javascript! :-)
    • 糟糕的 JavaScript ......它只是试图从一个孩子成熟到一个成年人,但不幸的是它卡在了焦虑的青少年阶段。
    • @HBP,顺便说一句,谢谢你的想法......这就是我回答的原因。
    • 这绝对是迄今为止我见过的最有趣的方法。
    猜你喜欢
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2018-08-30
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多