如何找到JavaScript中的调用者函数?

function main()
{
   Hello();
}

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

有没有办法找出调用堆栈?

GilGreen2020/03/10 10:34:29

As none of previous answers works like what I was looking for(getting just the last function caller not a function as a string or callstack) I post my solution here for those who are like me and hope this will work for them:

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();

达蒙樱梅2020/03/10 10:34:29

If you really need the functionality for some reason and want it to be cross-browser compatible and not worry for strict stuff and be forward compatible then pass a this reference:

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
}
村村老丝2020/03/10 10:34:29

Another way around this problem is to simply pass the name of the calling function as a parameter.

For example:

function reformatString(string, callerName) {

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

    return string;
}

Now, you could call the function like this:

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

    reformatString(myString, function.name);
}

My example uses a hard coded check of the function name, but you could easily use a switch statement or some other logic to do what you want there.

A村村2020/03/10 10:34:29

Try the following code:

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

Worked for me in Firefox-21 and Chromium-25.

阿飞古一A2020/03/10 10:34:29

In both ES6 and Strict mode, use the following to get the Caller function

console.log((new Error()).stack.split("\n")[2].trim().split(" ")[1])

Please note that, the above line will throw an exception, if there is no caller or no previous stack. Use accordingly.

达蒙小胖2020/03/10 10:34:29

Just want to let you know that on PhoneGap/Android the name doesnt seem to be working. But arguments.callee.caller.toString() will do the trick.

....2020/03/10 10:34:29

Try accessing this:

arguments.callee.caller.name
ProSam2020/03/10 10:34:29

*arguments.callee.caller由于arguments.caller弃用,因此使用起来更安全...

古一蛋蛋凯2020/03/10 10:34:29
function Hello() {
    alert(Hello.caller);
}
西里猴子2020/03/10 10:34:29

我会这样做:

function Hello() {
  console.trace();
}
Harry小卤蛋2020/03/10 10:34:29

我通常(new Error()).stack在Chrome中使用令人高兴的是,这还为您提供了调用方调用该函数的行号。缺点是它将堆栈的长度限制为10,这就是为什么我首先来到此页面的原因。

(我正在使用它在执行期间收集低级构造函数中的调用堆栈,以供日后查看和调试,因此设置断点是没有用的,因为它会被击中数千次)

2020/03/10 10:34:29

您可以使用Function.Caller来获取调用函数。使用arguments.caller的旧方法被认为已过时。

以下代码说明了其用法:

function Hello() { return Hello.caller;}

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

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

有关过时的arguments.caller的说明:https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments/caller

请注意Function.caller是非标准的:https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/caller

小哥猪猪2020/03/10 10:34:29

如果您不打算在IE <11中运行它,那么console.trace()将很适合。

function main() {
    Hello();
}

function Hello() {
    console.trace()
}

main()
// Hello @ VM261:9
// main @ VM261:4
梅JinJin十三2020/03/10 10:34:29

您可以获得完整的堆栈跟踪:

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

直到来电者是null

注意:这会在递归函数上造成无限循环。

Mandy小卤蛋凯2020/03/10 10:34:29

我知道您提到过“用Java语言编写”,但是如果目的是调试,我认为仅使用浏览器的开发人员工具会更容易。在Chrome中是这样的: 在此处输入图片说明 只需将调试器放在要调查堆栈的位置即可。

猿十三2020/03/10 10:34:29

回顾(并使其更加清晰)...

此代码:

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

等效于此:

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

显然,第一位操作员更易于移植,因为您可以更改函数的名称,例如从“ Hello”更改为“ Ciao”​​,仍然可以使整个过程正常进行。

在后者中,如果您决定重构被调用函数的名称(Hello),则必须更改其所有出现的位置:(

TomMandy2020/03/10 10:34:28
function Hello()
{
    alert("caller is " + Hello.caller);
}

请注意,此功能是非标准的,来自Function.caller

非标准
此功能是非标准的,不在标准范围内。不要在面向Web的生产站点上使用它:它不适用于每个用户。实现之间也可能存在很大的不兼容性,并且将来的行为可能会更改。


以下是2008年的旧答案,现代Javascript不再支持该答案:

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