Recently in the preparation of JS reverse hook class plug-in, and then need to obtain the current code execution location, convenient code positioning, so summarized below JavaScript how to output function call stack.
Demo code
function main() {
let a = fun('hello world')
console.log(a)
}
function fun(a) {
return a
}
main()
Copy the code
methods
console.trace()
Use the following
function main() {
let a = fun('hello world')
console.log(a)
}
function fun(a) {
console.trace('fun')
return a
}
main()
Copy the code
The output is
Trace: fun at fun (c:\Users\zeyu\Desktop\demo\main.js:7:11) at main (c:\Users\zeyu\Desktop\demo\main.js:2:11) at Object.<anonymous> (c:\Users\zeyu\Desktop\demo\main.js:11:1) at Module._compile (node:internal/modules/cjs/loader:1095:14) at Object.Module._extensions.. js (node:internal/modules/cjs/loader:1124:10) at Module.load (node:internal/modules/cjs/loader:975:32) at Function.Module._load (node:internal/modules/cjs/loader:816:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12) at node:internal/main/run_main_module:17:47 hello worldCopy the code
Console.trace () can pass in arguments that will eventually be printed directly after trace, like fun here, but only in the console
IE6 doesn’t support it, but it’s probably not used anymore
arguments.callee.caller
In non-strict mode, you can print arguments directly, which prints the arguments called, and the function called, as follows
function main() {
let a = fun('hello world')
console.log(a)
}
function fun(a) {
console.log(fun.caller.toString())
console.log(arguments)
console.log(arguments.callee.toString())
console.log(arguments.callee.caller.toString())
return a
}
main()
Copy the code
The output is
function main() {
let a = fun('hello world')
console.log(a)
}
[Arguments] { '0': 'hello world' }
function fun(a) {
console.log(fun.caller.toString())
console.log(arguments)
console.log(arguments.callee.toString())
console.log(arguments.callee.caller.toString())
return a
}
function main() {
let a = fun('hello world')
console.log(a)
}
hello world
Copy the code
Caller (fun.caller, arguments.callee.caller) print_function (toString); caller (fun.caller, arguments.callee.caller);
Caller is the upper function called by main. It is not difficult to find that each caller object has a caller attribute, namely the upper function of caller. As I am in node environment, I do not know what the caller is. ** Fun. caller and ‘arguments.callee.caller can print the upper function ** until caller is empty
[[FunctionLocation]] [FunctionLocation]] [FunctionLocation]] [FunctionLocation]]
To sum up:
Fun.caller == arguments.callee. Caller represents the execution environment of fun (upper function)
Arguments. callee stands for fun in progress
Premise: In non-strict mode
new Error().stack
As we all know, once the program fails, it will stop running directly and output an error message. The error message here includes the function called and the specific location. In contrast to the above method, this can be directly output in the execution environment, rather than simply displayed in the console.
The same code as above
function main() {
let a = fun('hello world')
console.log(a)
}
function fun(a) {
printStack()
return a
}
function printStack() {
let stack = (new Error()).stack
console.log(stack)
}
main()
Copy the code
The output is a string, as follows
Error at printStack (c:\Users\zeyu\Desktop\demo\main.js:12:16) at fun (c:\Users\zeyu\Desktop\demo\main.js:7:3) at main (c:\Users\zeyu\Desktop\demo\main.js:2:11) at Object.<anonymous> (c:\Users\zeyu\Desktop\demo\main.js:16:1) at Module._compile (node:internal/modules/cjs/loader:1095:14) at Object.Module._extensions.. js (node:internal/modules/cjs/loader:1124:10) at Module.load (node:internal/modules/cjs/loader:975:32) at Function.Module._load (node:internal/modules/cjs/loader:816:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12) at node:internal/main/run_main_module:17:47 hello worldCopy the code
Because the result is a string, we can split the function (fun) and call location (c:\Users\zeyu\Desktop\demo\main.js:7:3)
function main() {
let a = fun('hello world')
console.log(a)
}
function fun(a) {
printStack()
return a
}
main()
function printStack() {
const callstack = new Error().stack.split("\n");
callstack.forEach((s) = > {
let matchArray = s.match(/at (.+?) ((. +?) ) /)
if(! matchArray)return
let name = matchArray[1]
let location = matchArray[2]
console.log(name, location)
})
}
Copy the code
The output is as follows (since this is a Node environment, it will output something about modules)
printStack c:\Users\zeyu\Desktop\demo\main.js:14:21 fun c:\Users\zeyu\Desktop\demo\main.js:7:3 main c:\Users\zeyu\Desktop\demo\main.js:2:11 Object.<anonymous> c:\Users\zeyu\Desktop\demo\main.js:11:1 Module._compile node:internal/modules/cjs/loader:1095:14 Object.Module._extensions.. js node:internal/modules/cjs/loader:1124:10 Module.load node:internal/modules/cjs/loader:975:32 Function.Module._load node:internal/modules/cjs/loader:816:12 Function.executeUserEntryPoint [as runMain] node:internal/modules/run_main:79:12 hello worldCopy the code
conclusion
Console.trace () is the best option if you want to output the call stack during debugging, but it can only be displayed on the console, not used in the runtime environment
Arguments.callee. caller uses the premise of non-strict mode, so delete “use strict”; Code, but can directly print out the complete function, and call the parameters passed.
New Error().stack is equivalent to actively reporting an Error. Since an Error will automatically print the call information where the Error is reported, the function name, line and column of the code can be accurately located, and the location of the code to be located is preferred.