简体   繁体   English

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

[英]Can I get the name of the currently running function in JavaScript?

Is it possible to do this:是否有可能做到这一点:

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

I've got the Dojo and jQuery frameworks in my stack, so if either of those make it easier, they're available.我的堆栈中有 Dojo 和 jQuery 框架,所以如果其中任何一个更容易,它们都是可用的。

In ES5 and above, there is no access to that information.在 ES5 及更高版本中,无法访问该信息。

In older versions of JS you can get it by using arguments.callee .在旧版本的 JS 中,您可以使用arguments.callee来获取它。

You may have to parse out the name though, as it will probably include some extra junk.不过,您可能需要解析该名称,因为它可能包含一些额外的垃圾。 Though, in some implementations you can simply get the name using arguments.callee.name .不过,在某些实现中,您可以简单地使用arguments.callee.name获取名称。

Parsing:解析:

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

   alert(myName);
}

Source: Javascript - get current function name .来源: Javascript - 获取当前函数名称

For non-anonymous functions对于非匿名函数

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

But in case of an error handler the result would be the name of the error handler function, wouldn't it?但是在错误处理程序的情况下,结果将是错误处理程序函数的名称,不是吗?

All what you need is simple.您需要的一切都很简单。 Create function:创建函数:

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

After that whenever you need, you simply use:之后,无论何时需要,您只需使用:

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

foo() 
// Logs: "foo"

According to MDN根据MDN

Warning: The 5th edition of ECMAScript (ES5) forbids use of arguments.callee() in strict mode.警告: ECMAScript (ES5) 第 5 版禁止在严格模式下使用 arguments.callee()。 Avoid using arguments.callee() by either giving function expressions a name or use a function declaration where a function must call itself.避免使用arguments.callee() 通过给函数表达式一个名称或在函数必须调用自身的地方使用函数声明。

As noted this applies only if your script uses "strict mode".如上所述,这适用,如果你的脚本使用“严格模式”。 This is mainly for security reasons and sadly currently there's no alternative for this.这主要是出于安全原因,遗憾的是目前没有其他选择。

This should do it:这应该这样做:

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

For the caller, just use caller.toString() .对于调用者,只需使用caller.toString()

The getMyName function in the snippet below returns the name of the calling function.下面代码片段中的getMyName函数返回调用函数的名称。 It's a hack and relies on non-standard feature: Error.prototype.stack .这是一个 hack 并且依赖于非标准特性: Error.prototype.stack Note that format of the string returned by Error.prototype.stack is implemented differently in different engines, so this probably won't work everywhere:请注意, 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())

About other solutions: arguments.callee is not allowed in strict mode and Function.prototype.caller is non-standard and not allowed in strict mode .关于其他解决方案: arguments.callee 在严格模式下是不允许的,Function.prototype.caller非标准的,在严格模式下是不允许的

Here's a way that will work:这是一种有效的方法:

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

Then in your tests:然后在你的测试中:

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

});

Note that the third test will only work if the test is located in /util/functions请注意,第三个测试仅在测试位于 /util/functions 时才有效

This has to go in the category of "world's ugliest hacks", but here you go.这必须归入“世界上最丑陋的黑客”类别,但在这里。

First up, printing the name of the current function (as in the other answers) seems to have limited use to me, since you kind of already know what the function is!首先,打印当前函数的名称(如在其他答案中)似乎对我的用处有限,因为您已经知道该函数是什么!

However, finding out the name of the calling function could be pretty useful for a trace function.但是,找出调用函数的名称对于跟踪函数可能非常有用。 This is with a regexp, but using indexOf would be about 3x faster:这是使用正则表达式,但使用 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();

The name of the current function and how it can be obtained seems to have changed over the past 10 years, since this question was asked.自从提出这个问题以来,当前函数的名称及其获取方式在过去 10 年中似乎发生了变化。

Now, not being a pro web developer who knows about all the histories of all browsers ever having existed, here is how it works for me in a 2019 chrome browser:现在,我不是一个了解所有浏览器历史的专业 Web 开发人员,以下是它在 2019 年 chrome 浏览器中的工作原理:

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

Some of the other answers ran into some chrome errors about strict javascript code and whatnot.其他一些答案遇到了一些关于严格的 javascript 代码和诸如此类的 chrome 错误。

Another use case could be an event dispatcher bound at runtime:另一个用例可能是在运行时绑定的事件调度程序:

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

The advantage here is the dispatcher can be easily reused and doesn't have to receive the dispatch queue as an argument, instead it comes implicit with the invocation name...这里的优点是调度器可以很容易地重用,并且不必将调度队列作为参数接收,而是隐含地带有调用名称......

In the end, the general case presented here would be "using the function name as an argument so you don't have to pass it explicitly", and that could be useful in many cases, such as the jquery animate() optional callback, or in timeouts/intervals callbacks, (ie you only pass a funcion NAME).最后,这里介绍的一般情况是“使用函数名称作为参数,因此您不必显式传递它”,这在许多情况下可能很有用,例如 jquery animate() 可选回调,或者在超时/间隔回调中,(即你只传递一个函数名称)。

(function f() {
    console.log(f.name);  //logs f
})();

Typescript variation:打字稿变体:

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

f2(f1);  //Logs f1

Note only available in ES6/ES2015 compliant engines.注意仅在符合 ES6/ES2015 的引擎中可用。 For more see 更多信息请参见

Since you have written a function named foo and you know it is in myfile.js why do you need to get this information dynamically?既然您已经编写了一个名为foo的函数并且您知道它在myfile.js为什么您需要动态获取此信息?

That being said you can use arguments.callee.toString() inside the function (this is a string representation of the entire function) and regex out the value of the function name.话虽如此,您可以在函数内部使用arguments.callee.toString() (这是整个函数的字符串表示)并正则表达式输出函数名称的值。

Here is a function that will spit out its own name:这是一个会吐出自己名字的函数:

function foo() {
    re = /^function\s+([^(]+)/
    alert(re.exec(arguments.callee.toString())[1]);             
}

A combination of the few responses I've seen here.我在这里看到的几个回复的组合。 (Tested in FF, Chrome, IE11) (在 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);
}

Calling randomFunction() will alert a string that contains the function name.调用 randomFunction() 将警告包含函数名称的字符串。

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

An updated answer to this can can be found over at this answer: https://stackoverflow.com/a/2161470/632495可以在此答案中找到对此的更新答案: https : //stackoverflow.com/a/2161470/632495

and, if you don't feel like clicking:并且,如果您不想点击:

function test() {
  var z = arguments.callee.name;
  console.log(z);
}

Information is actual on 2016 year.信息以2016年的实际为准。


Results for function declaration函数声明的结果

Result in the Opera歌剧中的结果

>>> (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

Result in the Chrome结果在 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

Result in the NodeJS在 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

Does not work in the Firefox.在 Firefox 中不起作用。 Untested on the IE and the Edge.未在 IE 和 Edge 上测试。


Results for function expressions函数表达式的结果

Result in the NodeJS在 NodeJS 中的结果

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

Result in the Chrome结果在 Chrome

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

Does not work in the Firefox, Opera.不适用于 Firefox、Opera。 Untested on the IE and the Edge.未在 IE 和 Edge 上测试。

Notes:笔记:

  1. Anonymous function does not to make sense to check.匿名函数检查没有意义。
  2. Testing environment测试环境

~ $ 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

Here is a one liner:这是一个单班轮:

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

Like this:像这样:

    function logChanges() {
      let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
      console.log(whoami + ': just getting started.');
    }

This a variant of Igor Ostroumov's answer:这是Igor Ostroumov答案的变体:

If you would like to use it as a default value for a parameter, you need to consider a second level call to 'caller':如果您想将其用作参数的默认值,则需要考虑对“caller”进行二级调用:

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

This would dynamically allow for a reusable implementation in multiple functions.这将动态地允许在多个功能中实现可重用。

 function getFunctionsNameThatCalledThisFunction() { return getFunctionsNameThatCalledThisFunction.caller.caller.name; } function bar(myFunctionName = getFunctionsNameThatCalledThisFunction()) { alert(myFunctionName); } // pops-up "foo" function foo() { bar(); } function crow() { bar(); } foo(); crow();

If you want the file name too, here is that solution using the answer from F-3000 on another question:如果您也需要文件名,这里是使用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();
}

As arguments.callee.name is non-standard, and forbidden in ECMAScript 5 strict mode ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee ), a simple solution to dynamically retrieve function names [like magic variables] is the use of scoped variables, and the Function.name property.由于 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

Note: Nested functions cease to be source elements, and are hence not hoisted.注意:嵌套函数不再是源元素,因此不会被提升。 Also, this technique cannot work with anonymous functions.此外,这种技术不能用于匿名函数。

The arguments object is a local variable available within all non-arrow functions. arguments 对象是所有非箭头函数中可用的局部变量。
You can refer to a function's arguments inside that function by using its arguments object.您可以通过使用其参数对象来引用该函数内部的函数参数。
It has entries for each argument the function was called with, with the first entry's index at 0.它对调用函数的每个参数都有条目,第一个条目的索引为 0。

So you can basically use arguments.callee.name but inside named functions like this one:所以你基本上可以使用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

Unfortunately it is not usable inside arrow functions:不幸的是,它在箭头函数中不可用:

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)

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

尝试:

alert(arguments.callee.toString());

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM