function main()
{
   Hello();
}

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

有办法找到调用堆栈吗?


当前回答

注意,不能使用Function。Node.js中的caller,使用caller-id包代替。例如:

var callerId = require('caller-id');

function foo() {
    bar();
}
function bar() {
    var caller = callerId.getData();
    /*
    caller = {
        typeName: 'Object',
        functionName: 'foo',
        filePath: '/path/of/this/file.js',
        lineNumber: 5,
        topLevelFlag: true,
        nativeFlag: false,
        evalFlag: false
    }
    */
}

其他回答

试试下面的代码:

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里为我工作过。

你可以得到完整的堆栈跟踪:

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

直到调用者为空。

注意:它会导致递归函数的无限循环。

如果你出于某种原因真的需要这个功能,希望它能跨浏览器兼容,不担心严格的东西,并且向前兼容,那么传递一个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
}

2018年更新

严格模式下禁止调用。下面是使用(非标准)错误堆栈的替代方案。

下面的函数似乎在Firefox 52和Chrome 61-71中完成了这项工作,尽管它的实现对这两种浏览器的日志格式做了很多假设,应该谨慎使用,因为它会抛出一个异常,并可能在完成之前执行两个正则表达式匹配。

'use strict'; const fnNameMatcher = /([^(]+)@|at ([^(]+) \(/; function fnName(str) { const regexResult = fnNameMatcher.exec(str); return regexResult[1] || regexResult[2]; } function log(...messages) { const logLines = (new Error().stack).split('\n'); const callerName = fnName(logLines[1]); if (callerName !== null) { if (callerName !== 'log') { console.log(callerName, 'called log with:', ...messages); } else { console.log(fnName(logLines[2]), 'called log with:', ...messages); } } else { console.log(...messages); } } function foo() { log('hi', 'there'); } (function main() { foo(); }());

由于之前的答案都不像我所寻找的那样(只得到最后一个函数调用者,而不是作为字符串或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();