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

问题描述 投票:0回答:8

我需要将当前函数名称作为字符串记录到我们的日志工具中。但

arguments.callee.name
仅适用于松散模式。如何获取
"use strict"
下的函数名?

javascript strict
8个回答
42
投票

出于日志记录/调试目的,您可以在记录器中创建一个新的

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');
});


6
投票

您可以将函数绑定为其上下文,然后您可以通过

this.name
属性访问其名称:

function x(){
  console.log(this.name);
}
x.bind(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


3
投票

基于 @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'
}

2
投票

只是更新以获得全名:

function logIt(message) {
    var stack = new Error().stack,

    //  update is on this line
    caller = stack.split('\n')[2].trim().split(/\s+/)[1];

    console.log(caller.trim().split(/\s+/)[1];);
}

function a(b) {
  b()
}

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

0
投票

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

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

注意:嵌套函数不再是源元素,因此不会被提升。此外,该技术不能与匿名函数一起使用。


0
投票

2024 年...

console.log("TEST", arguments.callee.name)
// in fact, works fine on most systems, try it

// will crash console.log("TEST2", new.target.name)
// will crash console.log("TEST3", Function.prototype.caller)

但更好的是,基于@MaxHeiber令人难以置信的答案https://stackoverflow.com/a/39337724/294884

获取此姓名或来电者姓名..

const itsame = (new Error("")).stack.split('\n')[1].match(/at (\w+)/)[1]
const calledme = (new Error("")).stack.split('\n')[2].match(/at (\w+)/)[1]

console.log("i am", itsame, "and i was called by", calledme)

当然,您可能需要不时地修改正则表达式。

(这种东西很可能只会在开发代码中使用,就像我们将它用于代码生成之类的东西一样,所以这不是问题。)


-1
投票

如果(像我一样)你想在其他地方定义它并通用地调用它,你可以将代码作为字符串存储在全局某个地方或导入它,然后

eval()
它可以访问当前函数名称。 (使用 eval 将上下文保留在调用点。)

一定有一种方法可以在不使用字符串的情况下做到这一点,但无论如何。

SomeObject.whatFunc =
  'const s = new Error().stack;' +
  "const stackLine = new Error().stack.split('\\n')[2].trim();" +
  'const fncName = stackLine.match(/(?<=at )(.*)(?= \\()/gm)[0];' +
  'console.log(fncName);'

// Whereever you want the func name
function countBananas('weeee') {
  eval(SomeObject.whatFunc)
  // blah blah blah
}

countBananas() // logs 'countBananas'
© www.soinside.com 2019 - 2024. All rights reserved.