Могу ли я получить имя запущенной функции в JavaScript? - PullRequest
164 голосов
/ 18 июня 2009

Возможно ли это сделать:

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

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

Ответы [ 18 ]

175 голосов
/ 18 июня 2009

Вы можете получить его, используя 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 - получить имя текущей функции .

61 голосов
/ 18 июня 2009

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

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

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

30 голосов
/ 05 февраля 2018

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

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

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

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

foo() 
// Logs: "foo"
26 голосов
/ 23 января 2016

Согласно MDN

Предупреждение: 5-я редакция ECMAScript (ES5) запрещает использование arguments.callee () в строгом режиме. Избегайте использования arguments.callee (), либо присваивая выражениям функции имя, либо используйте объявление функции, где функция должна вызывать себя.

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

21 голосов
/ 18 июня 2009

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

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

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

10 голосов
/ 18 июня 2009

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

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

Однако, выяснение имени , вызывающего функцию , может быть весьма полезным для функции трассировки. Это с регулярным выражением, но использование 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();
8 голосов
/ 12 января 2017

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

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

3 голосов
/ 11 июня 2010

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

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

2 голосов
/ 06 сентября 2016

Функция 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 является нестандартным и не допускается в строгом режиме .

1 голос
/ 13 февраля 2015

Обновленный ответ на этот вопрос можно найти по этому ответу: https://stackoverflow.com/a/2161470/632495

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

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