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



можно ли сделать так:



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


У меня есть фреймворки Dojo и jQuery в моем стеке, поэтому, если любой из них упрощает работу, они доступны.

550   17  

17 ответов:

вы должны быть в состоянии сделать это с помощью 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-получить текущее имя функции.

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

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

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

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

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

для вызывающего абонента, просто используйте caller.toString().

по данным MDN

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

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

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

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

однако, узнав имя вызов функция может быть очень полезной для функции трассировки. Это с регулярным выражением, но с помощью indexOf будет около 3x быстрее:

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

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

me();

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

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

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

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

foo() 
// Logs: "foo"

вот как это будет работать:

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

The getMyName функция в приведенном ниже фрагменте возвращает имя вызывающей функции. Это хак и полагается на нестандартное характеристика: 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, '' );
                return stack
}

function foo(){
  return getMyName()
}

function bar() {
  return foo()
}

console.log(bar())

о других решениях:arguments.calleeне работает в строгом режиме и Function.prototype.caller это нестандартное, но имеет лучшую поддержку, чем Error.prototype.stack.

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

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

вот функция, которая выплюнет свое собственное имя:

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

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

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

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

сочетание нескольких ответов которые я видел здесь. (Протестировано в 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/

вот один лайнер:

    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 год.


результаты для объявления функции

результат в опере

>>> (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 и краю.


результаты для выражений функций

результат в NodeJS

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

в результате Хром

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

не работает в Firefox, Opera. Непроверенные на IE и краю.

Примечания:

  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
(function f() {
    console.log(f.name);  //logs f
})();

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

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

f2(f1);  //Logs f1

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

попробуй:

alert(arguments.callee.toString());

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

Comments

    Ничего не найдено.