【问题标题】:Get current function name in strict mode在严格模式下获取当前函数名
【发布时间】:2016-11-20 23:40:03
【问题描述】:

我需要将当前函数名作为字符串记录到我们的日志工具。但是arguments.callee.name 只能在松散模式下工作。如何获取"use strict"下的函数名?

【问题讨论】:

  • 如果你能够修改函数的主体来添加日志代码,你不能硬编码函数名吗?如果您可以从属性中读取它,您会有什么优势?
  • @nnnnnn 有人不断重命名函数但忘记更新日志行。

标签: javascript strict


【解决方案1】:

出于记录/调试目的,您可以在记录器中创建一个新的Error 对象并检查其.stack 属性,例如

function logIt(message) {
    var stack = new Error().stack,
        caller = stack.split('\n')[2].trim();
    console.log(caller + ":" + message);
}

function a(b) {
    b()
}

a(function xyz() {
    logIt('hello');
});

【讨论】:

  • 你的回答有点复杂,但说明了思路。
  • 一个很好的答案@georg。请注意,[2] 仅与此示例相关,例如,如果您有一个包含三个父函数的堆栈,在这种情况下,我们必须将 2 更改为 3
  • @hamism: stack[2] 始终是调用记录器的函数,无论堆栈有多深。
  • 现在这是一个非常好的主意 :)
  • 这是一个聪明的记录/调试解决方案。但是,对于考虑在生产代码中使用此功能的其他人(在我的情况下,用于事件跟踪),请注意:“此功能是非标准的,不在标准轨道上。请勿在面向Web:它不会对每个用户都有效。实现之间也可能存在很大的不兼容性,并且将来的行为可能会发生变化。” (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…)
【解决方案2】:

您可以将函数绑定为其上下文,然后您可以通过this.nameproperty 访问其名称:

function x(){
  console.log(this.name);
}
x.bind(x)();

【讨论】:

  • 这很聪明。
  • 这个很巧妙,但是bind的效果是永久的,不能再改变this的值,会导致bug。 Perharps,x.call(x) 可能是一个更好的解决方案
【解决方案3】:

经过一点研究,这里是一个很好的解决方案:

function getFnName(fn) {
  var f = typeof fn == 'function';
  var s = f && ((fn.name && ['', fn.name]) || fn.toString().match(/function ([^\(]+)/));
  return (!f && 'not a function') || (s && s[1] || 'anonymous');
}



function test(){
    console.log(getFnName(this));
}

test  = test.bind(test);

test(); // 'test'

来源:https://gist.github.com/dfkaye/6384439

【讨论】:

  • 但这在函数内部不起作用,除非您已经拥有对该函数的引用。 OP 要求替换 arguments.callee.name...
【解决方案4】:

基于@georg 解决方案,这个只返回函数名。请注意,如果从匿名函数调用它可能会失败

function getFncName() {
    const stackLine = (new Error())!.stack!.split('\n')[2].trim()
    const fncName = stackLine.match(/at Object.([^ ]+)/)?.[1]
    return fncName
}

function Foo() {
    console.log(getFncName()) // prints 'Foo'
}

【讨论】:

  • 这只适用于基于 Chromium 的浏览器
【解决方案5】:

动态检索函数名称 [如魔术变量] 的简单解决方案是使用作用域变量和 Function.name 属性。

{
  function foo() {
    alert (a.name);
  }; let a = foo
}
{
  function foo2() {
    alert(a.name)
  }; let a = foo2
};
foo();//logs foo
foo2();//logs foo2

注意:嵌套函数不再是源元素,因此不会被提升。此外,此技术不适用于匿名函数。

【讨论】:

    猜你喜欢
    • 2017-07-17
    • 1970-01-01
    • 2014-07-24
    • 2011-08-26
    • 1970-01-01
    • 2012-12-27
    • 2014-01-15
    • 2016-12-31
    相关资源
    最近更新 更多