Получить имя функции динамически [дублировать]

Если вы можете получить доступ к серверу через ssh и можете запускать свои собственные скрипты, вы можете сделать простой сервер fifo, используя php (хотя вам придется перекомпилировать php с поддержкой posix для fork [ ! d2]).

Сервер может быть написан во что угодно, вы, вероятно, можете легко это сделать в python.

Или простейшим решением будет отправка HttpRequest и не чтение возвращаемых данных, но сервер может уничтожить скрипт до его завершения.

Пример сервера :

  & lt;? php define ('FIFO_PATH', '/home/user/input.queue');  define ('FORK_COUNT', 10);  if (file_exists (FIFO_PATH)) {die (FIFO_PATH. 'существует, удалите его и повторите попытку. "." \n ");  } if (! file_exists (FIFO_PATH) & amp;! posix_mkfifo (FIFO_PATH, 0666)) {die ('Невозможно создать прослушивание fifo.'. "\n");  } $ pids = array ();  $ fp = fopen (FIFO_PATH, 'r +');  for ($ i = 0; $ i & lt; FORK_COUNT; ++ $ i) {$ pids [$ i] = pcntl_fork ();  if (! $ pids [$ i]) {echo "process (". posix_getpid (). ", id = $ i) \n";  while (true) {$ line = chop (fgets ($ fp));  if ($ line == 'quit' || $ line === false) break;  echo "(". posix_getpid (). ", id = $ i) :: $ line \n";  // $ data = json_decode ($ line);  // processData ($ data);  } Выход();  }} fclose ($ fp);  foreach ($ pids as $ pid) {pcntl_waitpid ($ pid, $ status);  } unlink (FIFO_PATH);  ? & GT;   

Пример клиента:

  & lt;? php define ('FIFO_PATH', '/home/user/input.queue');  if (! file_exists (FIFO_PATH)) {die (FIFO_PATH. 'не существует, убедитесь, что сервер fifo запущен.'. "\n");  } function postToQueue ($ data) {$ fp = fopen (FIFO_PATH, 'w +');  stream_set_blocking ($ fp, false);  // не блокируем $ data = json_encode ($ data).  "\n";  if (fwrite ($ fp, $ data)! = strlen ($ data)) {echo "Не мог сервер быть мертвым или где-то ошибка? \n";  } fclose ($ fp);  } $ i = 1000;  while (- $ i) {postToQueue (массив ('xx' = & gt; 21, 'yy' = & gt; array (1,2,3)));  }? & gt;   

144
задан informatik01 26 October 2013 в 03:18
поделиться

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 - получить текущее имя функции .

150
ответ дан this.lau_ 15 August 2018 в 23:31
поделиться
  • 1
    @Matt - Если вы собираетесь использовать онлайн-источник, процитируйте его. Ваш образец кода явно взят из tek-tips.com/viewthread.cfm?qid=1209619 , и он несправедлив к оригинальному автору, чтобы использовать его без предоставления кредита. – Andrew Hare 18 June 2009 в 19:41
  • 2
    @Andrew - Вы правы, я должен был это сказать. Это была быстрая копия / вставка / очистка от того, что я уже сделал с закладкой, и надзор с моей стороны. Спасибо, что добавили его в мой пост. – Matt 18 June 2009 в 20:04
  • 3
    Перерывы в строгом режиме ES5. – Raynos 1 July 2011 в 14:48
  • 4
    Ох ... вот почему люди всегда избивали меня на скорости, чтобы ответить. Я не думал об этом. – Erik Reppen 6 July 2012 в 14:56
  • 5
    если вы используете объектный литерал для своих методов и нет имени метода, то это не будет работать как аргументы. callee действует как анонимная функция, которая не будет содержать имени какой-либо функции. Вам нужно будет дважды добавить это имя функции. Взгляните на этот пример jsfiddle: jsfiddle.net/ncays . Другая проблема с этим, однако, заключается в том, что arguments.callee не допускается в строгом режиме. – hellatan 28 May 2013 в 16:48

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

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

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

function foo() {
    re = /^function\s+([^(]+)/
    alert(re.exec(arguments.callee.toString())[1]);             
}
1
ответ дан Andrew Hare 15 August 2018 в 23:31
поделиться
  • 1
    Я работаю над обработчиком ошибок, и я хочу сообщить о вызывающей функции. – sprugman 18 June 2009 в 16:15

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

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

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

21
ответ дан Andy E 15 August 2018 в 23:31
поделиться
  • 1
    Это сработало для меня, но я думаю, что в вашем регулярном выражении есть опечатка. Я должен был вынуть обратную косую черту перед [ – declan 13 February 2012 в 05:50
  • 2
    @declan: да, ты прав. Удивительно, что никто еще не указал, что в течение почти трех лет этот ответ был здесь :-) – Andy E 13 February 2012 в 17:13

Вот как это работает:

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 / функции

7
ответ дан Antoine 15 August 2018 в 23:31
поделиться

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

0
ответ дан buddamus 15 August 2018 в 23:31
поделиться

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

и, если вы не хотите, t чувствовать себя как щелчок:

function test() {
  var z = arguments.callee.name;
  console.log(z);
}
1
ответ дан Community 15 August 2018 в 23:31
поделиться

Попробуйте:

alert(arguments.callee.toString());
-2
ответ дан Deniz Dogan 15 August 2018 в 23:31
поделиться

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

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

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

51
ответ дан fforw 15 August 2018 в 23:31
поделиться

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

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

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

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

foo() 
// Logs: "foo"
7
ответ дан Igor Ostroumov 15 August 2018 в 23:31
поделиться

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

-7
ответ дан Jayant Bhawal 15 August 2018 в 23:31
поделиться
  • 1
    & Quot; ном & Quot; "& quot; имя & quot; На французском. Изменяется ли эта разновидность между языковыми версиями браузеров? Я бы так не подумал. – jeromeyers 16 December 2011 в 20:36
  • 2
    Он не работает в Chrome ... – Merc 22 February 2013 в 06:05

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

Сначала, напечатав имя функции 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();
10
ответ дан Krinkle 15 August 2018 в 23:31
поделиться

Согласно MDN

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

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

16
ответ дан Laimis 15 August 2018 в 23:31
поделиться

Функция 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, '$1' );
                return stack
}

function foo(){
  return getMyName()
}

function bar() {
  return foo()
}

console.log(bar())

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

2
ответ дан Max Heiber 15 August 2018 в 23:31
поделиться
  • 1
    очень круто! должен быть принятым ответом – kofifus 10 September 2016 в 11:49
  • 2
    расширьте это, чтобы также показать позицию в функции и поддержать анонимные функции с помощью: .replace (/ ^ \ s + at \ s (. +?) (?: \ s. *: |:) (. *?): (. * ?))? $ / g, '$ 1 ($ 2: $ 3)') – kofifus 10 September 2016 в 11:50
(function f() {
    console.log(f.name);  //logs f
})();

Изменение машинописного текста:

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

f2(f1);  //Logs f1

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

0
ответ дан Ole 15 August 2018 в 23:31
поделиться

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

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

3
ответ дан Sampiolin 15 August 2018 в 23:31
поделиться

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


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

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

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

Примечания:

  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
0
ответ дан Seti Volkylany 15 August 2018 в 23:31
поделиться

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

    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.');
    }
0
ответ дан VRMBW 15 August 2018 в 23:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: