function main()
{
   Hello();
}

function Hello()
{
  // How do you find out the caller function is 'main'?
}

, из

function Hello()
{
    alert("caller is "   Hello.caller);
}

Обратите внимание, что эта функция состоит из Обнаружение «недопустимая дата» Экземпляр даты в JavaScript — переполнение стека Нестандартный Function.caller:

Эта функция нестандартная и не соответствует стандартам. Не используйте его на рабочих сайтах, выходящих в Интернет: он не будет работать для каждого пользователя. Также могут быть большие несовместимости между реализациями, и поведение может измениться в будущем.
StackTrace


Ниже приводится старый ответ 2008 года, который больше не поддерживается в современном Javascript:

function Hello()
{
    alert("caller is "   arguments.callee.caller.toString());
}

кто-то уже сделал это

Вот соглашение о форматировании даты ; вот код проекта на GitHub Получить трассировку стека очень медленно, так что будьте осторожны (читайте Глядя на вывод

Но не все новости хороши:

  1. потребуется определить имена функций для трассировки стека, чтобы они были читаемыми. Потому что если у вас есть такой код: this для получения дополнительной информации).

  2. name, если вы не даете имя

    var Klass = function kls() {
       this.Hello = function() { alert(printStackTrace().join('nn')); };
    }
    new Klass().Hello();
    

    Google Chrome будет предупреждать ... kls.Hello ( ..., но большинство браузеров ожидают имя функции сразу после ключевого слова function, и он будет обрабатываться как анонимная функция. Даже Chrome не сможет использовать соблазн Klass функции. kls, но я не нашел любое реальное улучшение за счет этого.

    И, кстати, вы можете передать функции printStackTrace параметр {guess: true} Не все браузеры предоставляют одинаковую информацию. То есть параметры, столбец кода и т. д.

  3. Имя функции вызывающего абонента


Кстати, если вам нужно только имя Вызывающую функцию (в большинстве браузеров, но не в IE) вы можете использовать:

Но учтите, что это имя будет одним после

arguments.callee.caller.name

. Единственная кросс-браузерная и действительно безопасная вещь, которую вы можете использовать: function ключевое слово. Я не нашел способа (даже в Google Chrome) получить больше, чем без кода всей функции. Функция


Код функции вызывающей стороны

Часы обнуляются при создании даты «UTC». покажет код

arguments.callee.caller.toString();

, Который покажет код code , чем текущий процесс копирования копируется. Если нет, на копию, которая уже существует, следует ссылаться. Это делает необходимым ссылку с оригинала на его копию.

используя другой подход:

этот код:

function Hello() {
    alert("caller is "   arguments.callee.caller.toString());
}

эквивалентен этому:

function Hello() {
    alert("caller is "   Hello.caller.toString());
}

Очевидно, что первый бит более переносим, ​​так как вы можете изменить имя функции, скажи от «Привет» до «Чао», и все же заставь все это работать.

В последнем случае, если вы решите провести рефакторинг имени вызываемой функции (Hello), вам придется изменить все ее вхождения :(

Вы можете получить полную трассировку стека:

arguments.callee.caller
arguments.callee.caller.caller
arguments.callee.caller.caller.caller

и другие заголовки ответа CORS. Они не относятся к запросу, не делают ничего полезного (в чем смысл системы разрешений, где вы можете предоставить себе разрешение?) И должны появляться только в ответе. null Глядя на вывод

Примечание: это вызывает бесконечный цикл для рекурсивных функций.

Я знаю, что вы упомянули «в Javascript», но если целью является отладка, я думаю, что проще использовать инструменты разработчика вашего браузера. Вот как это выглядит в Chrome: enter image description here Просто бросьте отладчик, где вы хотите исследовать стек.

Я обычно использую (new Error()).stack Есть ли простой способ преобразования строки в регистр заголовков? Например. Джон Смит становится Джоном Смитом. Я не ищу что-то сложное, как решение Джона Резига, просто (надеюсь), какое-то одно -…

( Я использую это для сбора callstacks в низкоуровневом конструкторе во время выполнения, для просмотра и отладки позже, поэтому установка точки останова не используется, так как она будет достигнута тысячи раз)

Если вы не собираетесь запустите его в IE & lt ; 11 then console.trace () подойдет.

function main() {
    Hello();
}

function Hello() {
    console.trace()
}

main()
// Hello @ VM261:9
// main @ VM261:4

Вы можете использовать Function.Caller для получения вызывающей функции. Старый метод, использующий аргумент arguments.caller, считается устаревшим.

Следующий код иллюстрирует его use:

function Hello() { return Hello.caller;}

Hello2 = function NamedFunc() { return NamedFunc.caller; };

function main()
{
   Hello();  //both return main()
   Hello2();
}

Я хочу https: // разработчик. mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller

Я слышал, это называется «автоматическое управление версиями». Наиболее распространенный метод — включить mtime статического файла где-то в URL-адресе и удалить его с помощью обработчиков перезаписи или URL-адресов. А потом я обнаружил, что эта функция инвертирования из:

function Hello() {
    alert(Hello.caller);
}

Безопаснее использовать *arguments.callee.caller Это потому что arguments.caller, устарела

Когда вы хотите переименовать именованный импорт, это возможно с помощью , вызываемый не разрешен в «строгом режиме» , поэтому для собственного использования я написал класс, который получит путь от того места, где он вызывается. Это части небольшой вспомогательной библиотеки lib , и если вы хотите использовать автономный код, измените смещение, используемое для возврата st. ack trace of the caller (используйте 1 вместо 2)

function ScriptPath() {
  var scriptPath = '';
  try {
    //Throw an error to generate a stack trace
    throw new Error();
  }
  catch(e) {
    //Split the stack trace into each line
    var stackLines = e.stack.split('n');
    var callerIndex = 0;
    //Now walk though each line until we find a path reference
    for(var i in stackLines){
      if(!stackLines[i].match(/http[s]?:///)) continue;
      //We skipped all the lines with out an http so we now have a script reference
      //This one is the class constructor, the next is the getScriptPath() call
      //The one after that is the user code requesting the path info (so offset by 2)
      callerIndex = Number(i)   2;
      break;
    }
    //Now parse the string for each section we want to return
    pathParts = stackLines[callerIndex].match(/((http[s]?://. /)([^/] .js)):/);
  }

  this.fullPath = function() {
    return pathParts[1];
  };

  this.path = function() {
    return pathParts[2];
  };

  this.file = function() {
    return pathParts[3];
  };

  this.fileNoExt = function() {
    var parts = this.file().split('.');
    parts.length = parts.length != 1 ? parts.length - 1 : 1;
    return parts.join('.');
  };
}

Я бы сделал это:

function Hello() {
  console.trace();
}

Попробуйте получить доступ к этому:

arguments.callee.caller.name

Просто консольный журнал вашего стека ошибок. Затем вы можете узнать, как вас зовут

const hello = () => {
  console.log(new Error('I was called').stack)
}

const sello = () => {
  hello()
}

sello()

Я хотел бы добавить сюда свою скрипку для этого:

http://jsfiddle.net/bladnman/EhUm3/

Я проверял, что это Chrome, Safari и IE ( 10 и 8). Работает отлично. Имеет значение только 1 функция, поэтому, если вас пугает большая скрипка, читайте ниже.

Примечание: в этой скрипке довольно много моих собственных «шаблонов». Вы можете удалить все это и использовать сплит, если хотите. Это просто «сверхбезопасный» набор функций, на которые я могу положиться.

Там также есть шаблон «JSFiddle», который я использую для многих скрипок, чтобы просто быстро поиграться.

Если вам просто нужно имя функции, а не код, и вы хотите независимое от браузера решение, используйте следующее:

var callerFunction = arguments.callee.caller.toString().match(/function ([^(] )/)[1];

Обратите внимание, что вышеприведенное вернет ошибку, если нет функции вызывающей стороны, так как в массиве нет элемента [1]. Чтобы обойти это, используйте следующее:

var callerFunction = (arguments.callee.caller.toString().match(/function ([^(] )/) === null) ? 'Document Object Model': arguments.callee.caller.toString().match(/function ([^(] )/)[1], arguments.callee.toString().match(/function ([^(] )/)[1]);

caller запрещен в строгом режиме . Вот альтернатива с использованием (нестандартного) Error stack Глядя на вывод

Кажется, что следующая функция выполняет работу в Firefox 52 и Chrome 61-71, хотя его реализация делает много предположений о формате журналирования двух браузеров и должна использоваться с осторожностью, учитывая, что она выдает исключение и, возможно, выполняет два сопоставления с регулярным выражением перед выполнением.

'use strict';
const fnNameMatcher = /([^(] )@|at ([^(] ) (/;

function fnName(str) {
  const regexResult = fnNameMatcher.exec(str);
  return regexResult[1] || regexResult[2];
}

function log(...messages) {
  const logLines = (new Error().stack).split('n');
  const callerName = fnName(logLines[1]);

  if (callerName !== null) {
    if (callerName !== 'log') {
      console.log(callerName, 'called with:', ...messages);
    } else {
      console.log(fnName(logLines[2]), 'called with:', ...messages);
    }
  } else {
    console.log(...messages);
  }
}

function foo() {
  log('hi', 'there');
}

(function main() {
  foo();
}());

Просто хочу сообщить вам об этом на Я пытаюсь написать регулярное выражение, которое возвращает строку, которая находится между двумя другими строками , Например: я хочу получить строку, которая находится между строками «корова» и «молоко» обработчик name похоже, не работает. Но arguments.callee.caller.toString() добьется цели.

Здесь все, кроме объекта functionname убран из caller.toString() Если вы пишете приложение — внезапно начальное время загрузки не всегда так важно, как текущая производительность приложения, и оно начинает окупаться, загружая данные и код отдельно.

<!DOCTYPE html>
<meta charset="UTF-8">
<title>Show the callers name</title><!-- This validates as html5! -->
<script>
main();
function main() { Hello(); }
function Hello(){
  var name = Hello.caller.toString().replace(/s([^#] $|^[^s] s/g,'');
  name = name.replace(/s/g,'');
  if ( typeof window[name] !== 'function' )
    alert ("sorry, the type of " name " is "  typeof window[name]);
  else
    alert ("The name of the " typeof window[name] " that called is " name);
}
</script>

здесь есть функция для получения полной стековой трассировки :

function stacktrace() {
var f = stacktrace;
var stack = 'Stack trace:';
while (f) {
  stack  = 'n'   f.name;
  f = f.caller;
}
return stack;
}

ответ heystewart и В ответе JiarongWu оба упомянули, что объект Error имеет доступ к stack Глядя на вывод

http: //jsperf.com/min-an d-max-in-array / 3

function main() {
  Hello();
}

function Hello() {
  var stack;
  try {
    throw new Error();
  } catch (e) {
    stack = e.stack;
  }
  // N.B. stack === "Errorn  at Hello ...n  at main ... n...."
  var m = stack.match(/.*?Hello.*?n(.*?)n/);
  if (m) {
    var caller_name = m[1];
    console.log("Caller is:", caller_name)
  }
}

main();

Различные браузеры показывают стек в разных форматах строк:


Safari : Caller is: main@https://stacksnippets.net/js:14:8
Firefox : Caller is: main@https://stacksnippets.net/js:14:3
Chrome : Caller is: at main (https://stacksnippets.net/js:14:3)
IE Edge : Caller is: at main (https://stacksnippets.net/js:14:3)
IE : Caller is: at main (https://stacksnippets.net/js:14:3)

большинству браузеров установите стек с объектом var stack = (new Error()).stack Я вижу, что люди путаются, когда объявляют переменные с или без

Вывод: можно определить, что «main» является вызывающей стороной для «Hello», используя stack Если вы используете константы, у вас нет выбора: Error. Фактически он будет работать в тех случаях, когда подход callee / caller не работает. Он также покажет вам контекст, то есть исходный файл и номер строки. Однако необходимо приложить усилия, чтобы пересечь решение платформа.

Попробуйте следующий код:

function getStackTrace(){
  var f = arguments.callee;
  var ret = [];
  var item = {};
  var iter = 0;

  while ( f = f.caller ){
      // Initialize
    item = {
      name: f.name || null,
      args: [], // Empty array = no arguments passed
      callback: f
    };

      // Function arguments
    if ( f.arguments ){
      for ( iter = 0; iter<f.arguments.length; iter   ){
        item.args[iter] = f.arguments[iter];
      }
    } else {
      item.args = null; // null = argument listing not supported
    }

    ret.push( item );
  }
  return ret;
}

JavaScript Namespacing

Другим способом решения этой проблемы является просто передать имя вызывающей функции в качестве параметра.

Также смотрите

function reformatString(string, callerName) {

    if (callerName === "uid") {
        string = string.toUpperCase();
    }

    return string;
}

Затем я использовал этот HTML со встроенным CSS для высоты и ширины.

function uid(){
    var myString = "apples";

    reformatString(myString, function.name);
}

сравнения

Насколько я знаю, у нас есть 2 способа для этого из данных источников, таких как этот —

  1. arguments.caller

    function whoCalled()
    {
        if (arguments.caller == null)
           console.log('I was called from the global scope.');
        else
           console.log(arguments.caller   ' called me!');
    }
    
  2. Function.caller

    function myFunc()
    {
       if (myFunc.caller == null) {
          return 'The function was called from the top!';
       }
       else
       {
          return 'This function's caller was '   myFunc.caller;
        }
    }
    

Думаю, у вас есть ответ :).

demo:

Как узнать функцию вызывающего в JavaScript?

var stackTrace = function() {

    var calls = [];
    var caller = arguments.callee.caller;

    for (var k = 0; k < 10; k  ) {
        if (caller) {
            calls.push(caller);
            caller = caller.caller;
        }
    }

    return calls;
};

// when I call this inside specific method I see list of references to source method, obviously, I can add toString() to each call to see only function's content
// [function(), function(data), function(res), function(l), function(a, c), x(a, b, c, d), function(c, e)]

Я пытаюсь нг, чтобы ответить как на вопрос, так и на текущую награду с этим вопросом.

Для получения награды требуется, чтобы вызывающий абонент был получен в строгом , и единственный способ увидеть это — обратиться к объявленной функции normal строгом режиме.

Например, следующее является нестандартным, но было протестировано с предыдущими (29/03/2016) и текущими (1 августа 2018 года) версии Chrome, Edge и Firefox.

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

'use strict';
function main()
{
   // Original question:
   Hello();
   // Bounty question:
   (function() { console.log('Anonymous function called by '   caller().name); })();
}

function Hello()
{
   // How do you find out the caller function is 'main'?
   console.log('Hello called by '   caller().name);
}

main();

Если вам действительно по какой-то причине нужна эта функциональность и вы хотите, чтобы она была совместима с разными браузерами, не беспокоились о строгих вещах и были бы совместимы напрямую, тогда передайте следующую ссылку:

function main()
{
   Hello(this);
}

function Hello(caller)
{
    // caller will be the object that called Hello. boom like that... 
    // you can add an undefined check code if the function Hello 
    // will be called without parameters from somewhere else
}

Я думаю, следующий фрагмент кода может быть полезно:

window.fnPureLog = function(sStatement, anyVariable) {
    if (arguments.length < 1) { 
        throw new Error('Arguments sStatement and anyVariable are expected'); 
    }
    if (typeof sStatement !== 'string') { 
        throw new Error('The type of sStatement is not match, please use string');
    }
    var oCallStackTrack = new Error();
    console.log(oCallStackTrack.stack.replace('Error', 'Call Stack:'), 'n'   sStatement   ':', anyVariable);
}

Выполнить код:

window.fnPureLog = function(sStatement, anyVariable) {
    if (arguments.length < 1) { 
        throw new Error('Arguments sStatement and anyVariable are expected'); 
    }
    if (typeof sStatement !== 'string') { 
        throw new Error('The type of sStatement is not match, please use string');
    }
    var oCallStackTrack = new Error();
    console.log(oCallStackTrack.stack.replace('Error', 'Call Stack:'), 'n'   sStatement   ':', anyVariable);
}

function fnBsnCallStack1() {
    fnPureLog('Stock Count', 100)
}

function fnBsnCallStack2() {
    fnBsnCallStack1()
}

fnBsnCallStack2();

Журнал выглядит следующим образом:

Call Stack:
    at window.fnPureLog (<anonymous>:8:27)
    at fnBsnCallStack1 (<anonymous>:13:5)
    at fnBsnCallStack2 (<anonymous>:17:5)
    at <anonymous>:20:1 
Stock Count: 100

. А теперь используйте его во всем проекте, подобном следующему:

function getCallerName(func)
{
  if (!func) return "anonymous";
  let caller = func.caller;
  if (!caller) return "anonymous";
  caller = caller.toString();
  if (!caller.trim().startsWith("function")) return "anonymous";
  return caller.substring(0, caller.indexOf("(")).replace("function","");
}


//  Example of how to use "getCallerName" function

function Hello(){
console.log("ex1  =>  "   getCallerName(Hello));
}

function Main(){
Hello();

// another example
console.log("ex3  =>  "   getCallerName(Main));
}

Main();