我可以在JavaScript中获取当前运行的函数的名称吗?

spr*_*man 172 javascript jquery dojo

是否有可能做到这一点:

myfile.js:
function foo() {
    alert(<my-function-name>);
    // pops-up "foo"
    // or even better: "myfile.js : foo"
}
Run Code Online (Sandbox Code Playgroud)

我的堆栈中有Dojo和jQuery框架,所以如果其中任何一个更容易,它们就可用了.

Mat*_*att 187

你应该能够通过使用它来获得它arguments.callee.

你可能不得不解析这个名字,因为它可能包含一些额外的垃圾.但是,在某些实现中,您可以简单地使用名称arguments.callee.name.

解析:

function DisplayMyName() 
{
   var myName = arguments.callee.toString();
   myName = myName.substr('function '.length);
   myName = myName.substr(0, myName.indexOf('('));

   alert(myName);
}
Run Code Online (Sandbox Code Playgroud)

来源:Javascript - 获取当前的函数名称.

  • 在ES5严格模式下中断. (76认同)
  • @Andrew - 你是对的,我应该说的.这是我已经添加书签的快速复制/粘贴/清理,以及我的疏忽.感谢您将其添加到我的帖子中. (21认同)
  • @Matt - 如果您打算使用在线资源,请引用它.您的代码示例清楚地来自http://www.tek-tips.com/viewthread.cfm?qid=1209619,原始作者使用它而不给予信任是不公平的. (15认同)
  • 如果你正在使用方法的对象文字而没有实际的方法名称,那么这将不起作为arguments.callee就像一个匿名函数,它不会带任何函数名.您必须确保两次添加该函数名称.看看这个jsfiddle示例:http://jsfiddle.net/ncays/.但是,另一个问题是严格模式下不允许使用`arguments.callee`. (9认同)
  • 哦......这就是为什么人们总是以速度击败我来回复.我没有想到这一点. (2认同)
  • 我愿意打赌这个片段的原作者不关心引用. (2认同)

ffo*_*orw 67

对于非匿名函数

function foo()
{ 
    alert(arguments.callee.name)
}
Run Code Online (Sandbox Code Playgroud)

但是在错误处理程序的情况下,结果将是错误处理程序函数的名称,不是吗?

  • 值得记住:https://eslint.org/docs/rules/no-caller &gt;“在 JavaScript 的未来版本中已弃用,并且在严格模式下 ECMAScript 5 中禁止使用它们。” (3认同)
  • 不,不适用于Microsoft JScript. (2认同)
  • 这个想法似乎适用于Node.js. (2认同)
  • 在 Chrome 中运行良好。比接受的答案要好得多。 (2认同)

小智 37

你所需要的一切都很简单.创建功能:

function getFuncName() {
   return getFuncName.caller.name
}
Run Code Online (Sandbox Code Playgroud)

在您需要之后,您只需使用:

function foo() { 
  console.log(getFuncName())
}

foo() 
// Logs: "foo"
Run Code Online (Sandbox Code Playgroud)

  • 同样,不能在“严格模式”下使用,例如 ES6 类方法。 (6认同)
  • 谢谢,这比解析字符串要优雅得多. (2认同)

Lai*_*mis 28

MDN称

警告:第5版ECMAScript(ES5)禁止在严格模式下使用arguments.callee().避免使用arguments.callee()通过为函数表达式赋予名称或使用函数必须调用自身的函数声明.

如上所述,当您的脚本使用"严格模式" 时才适用.这主要是出于安全原因,遗憾的是目前没有替代方案.


And*_*y E 21

这应该这样做:

var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/);
alert(fn[1]);
Run Code Online (Sandbox Code Playgroud)

对于呼叫者,只需使用caller.toString().

  • 这对我有用,但我认为你的正则表达式中有一个错字.我不得不在`[`之前"取出反斜杠 (8认同)
  • @declan:是的,你是对的.令人惊讶的是,在这近三年的时间里,没有其他人指出过这个答案一直在这里:-) (4认同)
  • @AndyE 可能没有人指出这一点,因为一旦我们看到正则表达式,我们就会进入 TL;DR 模式并寻找其他答案;) (3认同)

Max*_*ber 20

getMyName下面片段中的函数返回调用函数的名称。这是一个 hack 并且依赖于非标准功能:Error.prototype.stack. 请注意,返回的字符串格式Error.prototype.stack在不同引擎中的实现方式不同,因此这可能不适用于所有地方:

function getMyName() {
  var e = new Error('dummy');
  var stack = e.stack
                .split('\n')[2]
                // " at functionName ( ..." => "functionName"
                .replace(/^\s+at\s+(.+?)\s.+/g, '$1' );
                return stack
}

function foo(){
  return getMyName()
}

function bar() {
  return foo()
}

console.log(bar())
Run Code Online (Sandbox Code Playgroud)

关于其他解决方案:arguments.callee 在严格模式下是不允许的Function.prototype.caller非标准的,在严格模式下不允许的

  • 扩展它也可以显示函数中的位置并支持匿名函数: .replace(/^\s+at\s(.+?)(?:\s.*:|:)(.*?):(.* ?)\)?$/g, '$1 ($2:$3)' ) (3认同)
  • 即使对于箭头功能也能完美工作,被低估的答案 (2认同)

Jam*_*ard 10

这必须属于"世界上最丑陋的黑客"的范畴,但是你走了.

首先,打印当前函数的名称(如在其他答案中)似乎对我有限,因为你已经知道函数是什么了!

但是,找出调用函数的名称对跟踪函数非常有用.这是一个正则表达式,但使用indexOf将快3倍:

function getFunctionName() {
    var re = /function (.*?)\(/
    var s = getFunctionName.caller.toString();
    var m = re.exec( s )
    return m[1];
}

function me() {
    console.log( getFunctionName() );
}

me();
Run Code Online (Sandbox Code Playgroud)


Ant*_*ony 8

这是一种可行的方式:

export function getFunctionCallerName (){
  // gets the text between whitespace for second part of stacktrace
  return (new Error()).stack.match(/at (\S+)/g)[1].slice(3);
}
Run Code Online (Sandbox Code Playgroud)

然后在你的测试中:

import { expect } from 'chai';
import { getFunctionCallerName } from '../../../lib/util/functions';

describe('Testing caller name', () => {

    it('should return the name of the function', () => {
      function getThisName(){
        return getFunctionCallerName();
      }

      const functionName = getThisName();

      expect(functionName).to.equal('getThisName');
    });

  it('should work with an anonymous function', () => {


    const anonymousFn = function (){
      return getFunctionCallerName();
    };

    const functionName = anonymousFn();

    expect(functionName).to.equal('anonymousFn');
  });

  it('should work with an anonymous function', () => {
    const fnName = (function (){
      return getFunctionCallerName();
    })();

    expect(/\/util\/functions\.js/.test(fnName)).to.eql(true);
  });

});
Run Code Online (Sandbox Code Playgroud)

请注意,第三个测试仅在测试位于/ util/functions中时才有效

  • 这是我使用的答案。本质上,它是一个单行解决方案。 (2认同)

Ami*_*ein 7

参数对象是所有非箭头函数中可用的局部变量。
您可以通过使用函数的参数对象来引用该函数内部的函数参数。
它具有调用函数所用的每个参数的条目,第一个条目的索引为 0。

所以你基本上可以arguments.callee.name在命名函数中使用 but ,如下所示:

function i_have_a_name() {
    console.log(`My name is:`, arguments.callee.name)
}
Run Code Online (Sandbox Code Playgroud)
> i_have_a_name()
My name is: i_have_a_name
Run Code Online (Sandbox Code Playgroud)

不幸的是它在箭头函数中不可用:

const i_have_a_name = () => {
    console.log(`My name is:`, arguments.callee.name)
}
Run Code Online (Sandbox Code Playgroud)
> i_have_a_name()
Uncaught ReferenceError: arguments is not defined
    at i_have_a_name (REPL3:2:32)
Run Code Online (Sandbox Code Playgroud)

来源:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments


Bit*_*ler 5

自从提出这个问题以来,当前函数的名称及其获取方式在过去 10 年中似乎发生了变化。

现在,我不是一个了解所有浏览器历史的专业 Web 开发人员,以下是它在 2019 年 chrome 浏览器中的工作原理:

function callerName() {
    return callerName.caller.name;
}
function foo() {
    let myname = callerName();
    // do something with it...
}
Run Code Online (Sandbox Code Playgroud)

其他一些答案遇到了一些关于严格的 javascript 代码和诸如此类的 chrome 错误。