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

JavaScript

Harry逆天

2020-03-10

function main()
{
   Hello();
}

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

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

第431篇《如何找到JavaScript中的调用者函数?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

17个回答
GilGreen 2020.03.10

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

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

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

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.

阿飞古一A 2020.03.10

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

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

Try accessing this:

arguments.callee.caller.name
ProSam 2020.03.10

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

古一蛋蛋凯 2020.03.10
function Hello() {
    alert(Hello.caller);
}
西里猴子 2020.03.10

我会这样做:

function Hello() {
  console.trace();
}
Harry小卤蛋 2020.03.10

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

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

null 2020.03.10

您可以使用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

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

function main() {
    Hello();
}

function Hello() {
    console.trace()
}

main()
// Hello @ VM261:9
// main @ VM261:4
梅JinJin十三 2020.03.10

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

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

直到来电者是null

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

Mandy小卤蛋凯 2020.03.10

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

猿十三 2020.03.10

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

此代码:

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

等效于此:

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

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

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

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

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

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


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

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

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android