How do you find out the caller function in JavaScr

2018-12-31 02:55发布

function main()
{
   Hello();
}

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

Is there a way to find out the call stack at all?

29条回答
琉璃瓶的回忆
2楼-- · 2018-12-31 03:23

A message from 2018 where accessing caller is forbidden:

The following function seems to do the job in Firefox 52 and Chrome 61 though its implementation makes a lot of assumptions about the logging format of the two browsers and should not be used for anything temporary developer debugging given that it throws an exception and possibly executes two regex matchings before being done.

let fnNameMatcher = /([^(]+)@|at ([^(]+) \(/;

function fnName(str) {
  let regexResult = fnNameMatcher.exec(str);
  return regexResult[1] || regexResult[2];
}

export function log(...messages: any[]) {
  let logLines = (new Error().stack).split('\n');
  let callerName = fnName(logLines[1]);

  if (callerName !== null) {
    if (callerName !== 'log') {
      console.log(callerName, ...messages);
    } else {
      console.log(fnName(logLines[2]), ...messages);
    }
  } else {
    console.log(...messages);
  }
}
查看更多
冷夜・残月
3楼-- · 2018-12-31 03:24
function Hello()
{
    alert("caller is " + Hello.caller);
}

Note that this feature is non standard, from Function.caller:

Non-standard
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.


The following is the old answer from 2008, which is no longer supported in modern Javascript:

function Hello()
{
    alert("caller is " + arguments.callee.caller.toString());
}
查看更多
姐姐魅力值爆表
4楼-- · 2018-12-31 03:25

I usually use (new Error()).stack in Chrome. The nice thing is that this also gives you the line numbers where the caller called the function. The downside is that it limits the length of the stack to 10, which is why I came to this page in the first place.

(I'm using this to collect callstacks in a low-level constructor during execution, to view and debug later, so setting a breakpoint isn't of use since it will be hit thousands of times)

查看更多
美炸的是我
5楼-- · 2018-12-31 03:27

I would do this:

function Hello() {
  console.trace();
}
查看更多
只若初见
6楼-- · 2018-12-31 03:27

heystewart's answer and JiarongWu's answer both mentioned that the Error object has access to the stack.

Here's an example:

function main() {
  Hello();
}

function Hello() {
  var stack;
  try {
    throw new Error();
  } catch (e) {
    stack = e.stack;
  }
  // N.B. stack === "Error\n  at Hello ...\n  at main ... \n...."
  var m = stack.match(/.*?Hello.*?\n(.*?)\n/);
  if (m) {
    var caller_name = m[1];
    console.log("Caller is:", caller_name)
  }
}

main();

Different browsers shows the stack in different string formats:

Safari : Caller is: main@https://stacksnippets.net/js:14:8 Firefox : Caller is: main@https://stacksnippets.net/js:14:3 Chrome : Caller is: at main (https://stacksnippets.net/js:14:3) IE Edge : Caller is: at main (https://stacksnippets.net/js:14:3) IE : Caller is: at main (https://stacksnippets.net/js:14:3)

Most browsers will set the stack with var stack = (new Error()).stack. In Internet Explorer the stack will be undefined - you have to throw a real exception to retrieve the stack.

Conclusion: It's possible to determine "main" is the caller to "Hello" using the stack in the Error object. In fact it will work in cases where the callee / caller approach doesn't work. It will also show you context, i.e. source file and line number. However effort is required to make the solution cross platform.

查看更多
姐姐魅力值爆表
7楼-- · 2018-12-31 03:27

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
}
查看更多
登录 后发表回答