Как вы узнаете функцию вызова в JavaScript? - PullRequest
800 голосов
/ 11 ноября 2008
function main()
{
   Hello();
}

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

Есть ли способ узнать стек вызовов?

Ответы [ 29 ]

955 голосов
/ 11 ноября 2008
function Hello()
{
    alert("caller is " + Hello.caller);
}

Обратите внимание, что эта функция нестандартная , из Function.caller:

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


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

function Hello()
{
    alert("caller is " + arguments.callee.caller.toString());
}
146 голосов
/ 24 сентября 2010

StackTrace

Вы можете найти всю трассировку стека, используя специальный код браузера. Хорошо, что кто-то уже сделал это ; Вот код проекта на GitHub .

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

  1. Очень медленно получить трассировку стека, поэтому будьте осторожны (подробнее читайте это ).

  2. Вам нужно определить имена функций для трассировки стека, чтобы они были разборчивыми. Потому что, если у вас есть такой код:

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

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

    И, между прочим, вы можете передать функции printStackTrace параметр {guess: true}, но я не нашел реального улучшения, сделав это.

  3. Не все браузеры предоставляют одинаковую информацию. То есть параметры, столбец кода и т. Д.


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

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

arguments.callee.caller.name

Но учтите, что это имя будет одним после ключевого слова function. Я не нашел способа (даже в Google Chrome) получить больше, чем без кода всей функции.


Код функции звонящего по телефону

И суммируя остальные лучшие ответы (Пабло Кабрера, Нурдин и Грег Хьюгилл). Единственная кросс-браузерная и действительно безопасная вещь, которую вы можете использовать:

arguments.callee.caller.toString();

Который покажет код функции вызывающего абонента. К сожалению, этого недостаточно для меня, и именно поэтому я даю вам подсказки для StackTrace и функции вызывающей стороны Name (хотя они не являются кросс-браузерными).

50 голосов
/ 06 апреля 2009

Подведем итоги (и проясним) ...

этот код:

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

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

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

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

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

50 голосов
/ 29 октября 2010

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

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

Пока абонент не наберет null.

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

41 голосов
/ 03 февраля 2015

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

36 голосов
/ 07 мая 2015

Я обычно использую (new Error()).stack в Chrome. Приятно то, что это также дает вам номера строк, где вызывающая сторона вызывала функцию. Недостатком является то, что он ограничивает длину стека до 10, поэтому я и пришел на эту страницу в первую очередь.

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

28 голосов
/ 18 января 2016

Если вы не собираетесь запускать его в IE <11, тогда <a href="https://developer.mozilla.org/en-US/docs/Web/API/Console/trace" rel="noreferrer"> console.trace () подойдет.

function main() {
    Hello();
}

function Hello() {
    console.trace()
}

main()
// Hello @ VM261:9
// main @ VM261:4
21 голосов
/ 07 июня 2015

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

Следующий код иллюстрирует его использование:

function Hello() { return Hello.caller;}

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

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

Замечания об устаревшем аргументе. Caller: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller

Имейте в виду, что Function.caller нестандартный: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller

18 голосов
/ 11 ноября 2008
function Hello() {
    alert(Hello.caller);
}
18 голосов
/ 11 ноября 2008

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

...