Могу ли я получить имя запущенной функции в JavaScript?

Можно ли сделать это:

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

У меня в стеке есть каркасы Dojo и jQuery, поэтому, если они облегчают работу, они доступны.

Ответы на вопрос(18)

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

Пытаться:

alert(arguments.callee.toString());
 30 нояб. 2016 г., 20:36
ЭТО НЕПРАВИЛЬНЫЙ ОТВЕТ. @ Энди Эрншоу прав.
 18 июн. 2009 г., 18:00
Это вернет всю функцию в виде строки

Информация актуальна на 2016 год.

Results for function declaration

Результат в Опере

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

Results for function expressions

Результат в 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.

Заметки:

Anonymous function does not to make sense to check. 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
(function f() {
    console.log(f.name);  //logs f
})();

Вариант машинописного текста:

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

f2(f1);  //Logs f1

Примечание доступно только в двигателях, соответствующих ES6 / ES2015.Для более см.

Решение Вопроса

Вы должны быть в состоянии получить это с помощью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);
}

Source: Javascript - get current function name.

 01 июл. 2011 г., 15:48
Перерывы в строгом режиме ES5.
 06 июл. 2012 г., 15:56
Ох ... вот почему люди всегда бьют меня по скорости, чтобы ответить. Я не думал об этом.
 18 июн. 2009 г., 21:04
@ Андрей - Вы правы, я должен был это заявить. Это было быстрое копирование / вставка / очистка того, что я уже добавил в закладки, и упущение с моей стороны. Спасибо за добавление его в мой пост.
 18 июн. 2009 г., 20:41
@ Matt - Если вы собираетесь использовать онлайн-источник, пожалуйста, укажите его. Ваш пример кода явно взят изtek-tips.com/viewthread.cfm?qid=1209619 и это несправедливо по отношению к первоначальному автору, чтобы использовать его, не отдавая должное.
 28 мая 2013 г., 17:48
если вы используете литерал объекта для своих методов и не используете фактическое имя метода, то это не будет работать в качестве arguments.callee действует как анонимная функция, которая не будет содержать никакого имени функции. Вы должны убедиться, что вы добавили это имя функции дважды. Посмотрите на этот пример jsfiddle:jsfiddle.net/ncays, другая проблема с этим, однако, в том, чтоarguments.callee не допускается в строгом режиме.

Обновленный ответ на это может быть найден в этом ответе: https://stackoverflow.com/a/2161470/632495

и, если вы не хотите нажимать:

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

Все, что вам нужно, это просто. Создать функцию:

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

После этого, когда вам нужно, вы просто используете:

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

foo() 
// Logs: "foo"
 26 авг. 2018 г., 23:23
Это должен быть принятый ответ.
 20 сент. 2018 г., 19:57
Кажется, это лучший ответ!
 01 мар. 2018 г., 13:20
Спасибо, это намного элегантнее, чем анализ строки.

getMyName Функция во фрагменте ниже возвращает имя вызывающей функции. Это взломать и полагаться нанестандартный особенность: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являетсянестандартный и не допускается в строгом режиме.

 10 сент. 2016 г., 13:50
расширить это, чтобы также показывать позицию в функции и поддерживать анонимные функции с помощью: .replace (/ ^ \ s + at \ s (. +?) (?: \ s. *: |:) (. *?): (. * ?))? $ / г, '$ 1 ($ 2: $ 3)' )
 10 сент. 2016 г., 13:49
очень очень круто! должен быть принятый ответ
 26 нояб. 2018 г., 16:33
Function.prototype.caller также не разрешен в строгом режиме.

В соответствии сMDN

Warning: The 5th edition of ECMAScript (ES5) forbids use of arguments.callee() in strict mode. Avoid using arguments.callee() by either giving function expressions a name or use a function declaration where a function must call itself.

Как уже отмечалось, это относитсяonly если ваш скрипт использует «строгий режим». Это в основном по соображениям безопасности и, к сожалению, в настоящее время альтернативы этому нет.

Вот способ, который будет работать:

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

Другим вариантом использования может быть диспетчер событий, связанный во время выполнения:

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 (). или в обратных вызовах по таймаутам / интервалам (т. е. вы передаете только имя функции).

Это вариантИгорь Остроумов ответ:

Если вы хотите использовать его в качестве значения по умолчанию для параметра, вам необходимо рассмотреть вызов второго уровня к «вызывающему»:

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

Это должно относиться к категории «самых уродливых хаков мира», но вот, пожалуйста.

Сначала напечатайте имяcurrent Мне кажется, что функция (как и в других ответах) имеет ограниченное применение, так как вы уже знаете, что это за функция!

Однако, узнав имяcalling Функция может быть очень полезна для функции трассировки. Это с регулярным выражением, но использование 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();
 22 авг. 2018 г., 20:51
Знание имени текущей функции может быть важно, если эта функция создается динамически из базы данных и нуждается в контекстной информации внутри функции, которая связана с именем функции.
 05 сент. 2016 г., 22:36
классное решение, но FYI Function # звонящий нестандартноdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Так как вы написали функцию с именемfoo и вы знаете, что это вmyfile.js зачем вам динамически получать эту информацию?

Это, как говорится, вы можете использоватьarguments.callee.toString() внутри функции (это строковое представление всей функции) и переделайте значение имени функции.

Вот функция, которая выдаст свое собственное имя:

function foo() {
    re = /^function\s+([^(]+)/
    alert(re.exec(arguments.callee.toString())[1]);             
}
 sprugman18 июн. 2009 г., 17:15
Я работаю над обработчиком ошибок и хочу сообщить о вызывающей функции.

Комбинация нескольких ответов, которые я здесь видел. (Проверено в 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 Fiddle Demo:http://jsfiddle.net/mjgqfhbe/

Это должно сделать это:

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

Для звонящего просто используйтеcaller.toString().

 13 февр. 2012 г., 16:13
@declan: да, вы правы. Удивительно, что никто другой не указал, что за почти 3 года этот ответ был здесь :-)
 13 февр. 2012 г., 04:50
Это сработало для меня, но я думаю, что в вашем регулярном выражении есть опечатка. Я должен был убрать обратную косую черту до того, как[

Для неанонимных функций

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

Но в случае обработчика ошибок результатом будет имя функции обработчика ошибок, не так ли?

 18 июн. 2009 г., 17:21
Это работает в IE / JScript?
 20 июн. 2015 г., 00:56
работает в Node.js
 08 июл. 2014 г., 04:16
Эта идея, кажется, работает в Node.js.
 18 июн. 2009 г., 17:31
Нет, не работает с Microsoft JScript.
 20 апр. 2013 г., 06:23
Мой не будет работать, например, методы / API :-(

Ответ короткий:alert(arguments.callee.name);

 22 февр. 2013 г., 05:05
Это не работает в Chrome ...
 16 дек. 2011 г., 19:36
& Quot; ном & Quot; это & quot; имя & quot; На французском. Меняется ли такая детализация между языковыми версиями браузеров? Я бы так не думал.

Ваш ответ на вопрос