214

是否有可能做到这一点:

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

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

4

21 回答 21

213

在 ES5 及更高版本中,无法访问该信息。

在旧版本的 JS 中,您可以使用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);
}

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

于 2009-06-18T15:15:52.350 回答
87

对于非匿名函数

function foo()
{ 
    alert(arguments.callee.name)
}

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

于 2009-06-18T15:19:31.797 回答
71

您所需要的一切都很简单。创建函数:

function getFuncName() {
   return getFuncName.caller.name
}

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

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

foo() 
// Logs: "foo"
于 2018-02-04T23:10:59.433 回答
36

根据MDN

警告: ECMAScript (ES5) 第 5 版禁止在严格模式下使用 arguments.callee()。避免使用 arguments.callee(),方法是给函数表达式命名或在函数必须调用自身的地方使用函数声明。

如前所述,这仅适用于的脚本使用“严格模式”的情况。这主要是出于安全原因,遗憾的是目前没有其他选择。

于 2016-01-23T16:33:14.280 回答
22

下面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())

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

于 2016-09-05T21:09:47.010 回答
21

这应该这样做:

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

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

于 2009-06-18T15:20:23.447 回答
14

这是一种可行的方法:

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

然后在你的测试中:

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

});

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

于 2017-01-12T19:34:04.800 回答
11

这必须归类为“世界上最丑陋的黑客”,但你去吧。

首先,打印当前函数的名称(如其他答案)似乎对我来说用途有限,因为您已经知道该函数是什么!

但是,找出调用函数的名称对于跟踪函数可能非常有用。这是使用正则表达式,但使用 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();
于 2009-06-18T15:29:47.797 回答
5

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

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

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

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

于 2019-11-09T00:10:40.707 回答
3

另一个用例可能是在运行时绑定的事件调度程序:

MyClass = function () {
  this.events = {};

  // Fire up an event (most probably from inside an instance method)
  this.OnFirstRun();

  // Fire up other event (most probably from inside an instance method)
  this.OnLastRun();

}

MyClass.prototype.dispatchEvents = function () {
  var EventStack=this.events[GetFunctionName()], i=EventStack.length-1;

  do EventStack[i]();
  while (i--);
}

MyClass.prototype.setEvent = function (event, callback) {
  this.events[event] = [];
  this.events[event].push(callback);
  this["On"+event] = this.dispatchEvents;
}

MyObject = new MyClass();
MyObject.setEvent ("FirstRun", somecallback);
MyObject.setEvent ("FirstRun", someothercallback);
MyObject.setEvent ("LastRun", yetanothercallback);

这里的优点是调度程序可以轻松重用,并且不必接收调度队列作为参数,而是隐含调用名称......

最后,这里介绍的一般情况是“使用函数名称作为参数,因此您不必显式传递它”,这在许多情况下可能很有用,例如 jquery animate() 可选回调,或在超时/间隔回调中,(即您只传递一个函数名称)。

于 2010-06-11T03:27:01.307 回答
3
(function f() {
    console.log(f.name);  //logs f
})();

打字稿变体:

function f1() {} 
function f2(f:Function) {
   console.log(f.name);
}

f2(f1);  //Logs f1

注意仅在 ES6/ES2015 兼容引擎中可用。 更多见

于 2018-06-22T13:59:01.060 回答
1

既然您已经编写了一个名为的函数foo并且您知道它在myfile.js为什么需要动态获取此信息?

话虽如此,您可以arguments.callee.toString()在函数内部使用(这是整个函数的字符串表示形式)并正则表达式输出函数名称的值。

这是一个会吐出自己名字的函数:

function foo() {
    re = /^function\s+([^(]+)/
    alert(re.exec(arguments.callee.toString())[1]);             
}
于 2009-06-18T15:14:00.793 回答
1

我在这里看到的几个回复的组合。(在 FF、Chrome、IE11 中测试)

function functionName() 
{
   var myName = functionName.caller.toString();
   myName = myName.substr('function '.length);
   myName = myName.substr(0, myName.indexOf('('));
   return myName;
}

function randomFunction(){
    var proof = "This proves that I found the name '" + functionName() + "'";
    alert(proof);
}

调用 randomFunction() 将警告包含函数名称的字符串。

JS 小提琴演示:http: //jsfiddle.net/mjgqfhbe/

于 2014-07-25T13:33:55.350 回答
1

可以在此答案中找到对此的更新答案: https ://stackoverflow.com/a/2161470/632495

并且,如果您不想点击:

function test() {
  var z = arguments.callee.name;
  console.log(z);
}
于 2015-02-13T05:11:48.953 回答
1

信息以 2016 年为准。


函数声明的结果

结果在歌剧院

>>> (function func11 (){
...     console.log(
...         'Function name:',
...         arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
... })();
... 
... (function func12 (){
...     console.log('Function name:', arguments.callee.name)
... })();
Function name:, func11
Function name:, func12

结果在 Chrome

(function func11 (){
    console.log(
        'Function name:',
        arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
})();

(function func12 (){
    console.log('Function name:', arguments.callee.name)
})();
Function name: func11
Function name: func12

结果在 NodeJS

> (function func11 (){
...     console.log(
.....         'Function name:',
.....         arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
... })();
Function name: func11
undefined
> (function func12 (){
...     console.log('Function name:', arguments.callee.name)
... })();
Function name: func12

在 Firefox 中不起作用。在 IE 和 Edge 上未经测试。


函数表达式的结果

结果在 NodeJS

> var func11 = function(){
...     console.log('Function name:', arguments.callee.name)
... }; func11();
Function name: func11

结果在 Chrome

var func11 = function(){
    console.log('Function name:', arguments.callee.name)
}; func11();
Function name: func11

不适用于 Firefox、Opera。在 IE 和 Edge 上未经测试。

笔记:

  1. 匿名功能检查没有意义。
  2. 测试环境

~ $ google-chrome --version
Google Chrome 53.0.2785.116           
~ $ opera --version
Opera 12.16 Build 1860 for Linux x86_64.
~ $ firefox --version
Mozilla Firefox 49.0
~ $ node
node    nodejs  
~ $ nodejs --version
v6.8.1
~ $ uname -a
Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
于 2016-11-30T20:18:10.997 回答
1

由于 arguments.callee.name 是非标准的,并且在 ECMAScript 5 严格模式(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee)中被禁止,一个简单的动态检索函数名称[如魔术变量]的解决方案是使用范围变量和 Function.name 属性。

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

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

于 2021-07-25T15:05:52.997 回答
0

这是一个单行:

    arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')

像这样:

    function logChanges() {
      let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
      console.log(whoami + ': just getting started.');
    }
于 2016-11-03T15:27:42.550 回答
0

这是Igor Ostroumov答案的变体:

如果您想将其用作参数的默认值,则需要考虑对“调用者”进行第二级调用:

function getFunctionsNameThatCalledThisFunction()
{
  return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}

这将动态地允许在多个功能中实现可重用。

function getFunctionsNameThatCalledThisFunction()
{
  return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}

function bar(myFunctionName = getFunctionsNameThatCalledThisFunction())
{ 
  alert(myFunctionName);
}

// pops-up "foo"
function foo()
{
  bar();
}

function crow()
{
  bar();
}

foo();
crow();

如果您也想要文件名,这是使用F-3000回答另一个问题的解决方案:

function getCurrentFileName()
{
  let currentFilePath = document.scripts[document.scripts.length-1].src 
  let fileName = currentFilePath.split('/').pop() // formatted to the OP's preference

  return fileName 
}

function bar(fileName = getCurrentFileName(),  myFunctionName = getFunctionsNameThatCalledThisFunction())
{
  alert(fileName + ' : ' + myFunctionName);
}

// or even better: "myfile.js : foo"
function foo()
{
  bar();
}
于 2019-02-12T17:00:11.427 回答
0

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

因此,您基本上可以使用arguments.callee.name但在命名函数中,如下所示:

function i_have_a_name() {
    console.log(`My name is:`, arguments.callee.name)
}
> i_have_a_name()
My name is: i_have_a_name

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

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

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

于 2022-01-19T05:18:26.323 回答
-1

尝试:

alert(arguments.callee.toString());
于 2009-06-18T15:14:18.997 回答
-7

答案很简短:alert(arguments.callee.name);

于 2011-07-20T10:59:33.313 回答