function main()
{
   Hello();
}

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

有办法找到调用堆栈吗?


当前回答

概括一下(并说得更清楚)…

这段代码:

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

等价于:

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

显然,第一部分更容易移植,因为你可以改变函数的名字,从“Hello”说成“Ciao”,但仍然可以让整个程序正常工作。

在后一种情况下,如果你决定重构被调用函数的名称(Hello),你将不得不改变它的所有出现:

其他回答

概括一下(并说得更清楚)…

这段代码:

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

等价于:

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

显然,第一部分更容易移植,因为你可以改变函数的名字,从“Hello”说成“Ciao”,但仍然可以让整个程序正常工作。

在后一种情况下,如果你决定重构被调用函数的名称(Hello),你将不得不改变它的所有出现:

对我来说很好,你可以在函数中选择你想要返回的程度:

function getCaller(functionBack= 0) {
    const back = functionBack * 2;
    const stack = new Error().stack.split('at ');
    const stackIndex = stack[3 + back].includes('C:') ? (3 + back) : (4 + back);
    const isAsync = stack[stackIndex].includes('async');
    let result;
    if (isAsync)
      result = stack[stackIndex].split(' ')[1].split(' ')[0];
    else
      result = stack[stackIndex].split(' ')[0];
    return result;
}

如果你出于某种原因真的需要这个功能,希望它能跨浏览器兼容,不担心严格的东西,并且向前兼容,那么传递一个this引用:

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
}

如果你只想要函数名而不是代码,并且想要一个独立于浏览器的解决方案,请使用以下方法:

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

试试下面的代码:

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

在火狐21和Chromium-25里为我工作过。