在严格模式下获取当前函数名

Posted

技术标签:

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

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

【问题讨论】:

如果你能够修改函数的主体来添加日志代码,你不能硬编码函数名吗?如果您可以从属性中读取它,您会有什么优势? @nnnnnn 有人不断重命名函数但忘记更新日志行。 【参考方案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

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

【讨论】:

以上是关于在严格模式下获取当前函数名的主要内容,如果未能解决你的问题,请参考以下文章

js:当前函数获取调用它的函数

JS严格模式

严格模式 丨JavaScript 函数进阶

3基本概念

js_递归函数在严格模式下的调用方法

JS严格模式