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

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

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

Ответы [ 29 ]

4 голосов
/ 12 сентября 2012

Здесь все, кроме functionname вырезано из caller.toString(), с RegExp.

<!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>
1 голос
/ 07 февраля 2017

Почему все приведенные выше решения выглядят как ракетостроение. Между тем, это не должно быть сложнее, чем этот фрагмент. Все кредиты этому парню

Как узнать функцию вызова в 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)]
1 голос
/ 29 марта 2016

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

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

Например, следующее является нестандартным, но было протестировано с предыдущими (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();
1 голос
/ 23 июня 2013

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

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;
}

Работал для меня в Firefox-21 и Chromium-25.

1 голос
/ 04 марта 2016

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

Например:

function reformatString(string, callerName) {

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

    return string;
}

Теперь вы можете вызвать функцию следующим образом:

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

    reformatString(myString, function.name);
}

В моем примере используется жестко заданная проверка имени функции, но вы можете легко использовать оператор switch или какую-то другую логику, чтобы делать то, что вы хотите.

1 голос
/ 28 марта 2016

Насколько я знаю, у нас есть 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;
        }
    }
    

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

0 голосов
/ 03 ноября 2015

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

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
}
0 голосов
/ 22 октября 2018

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

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();
0 голосов
/ 28 апреля 2017

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

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
...