Let's say that you have a bunch of functions that do different things, but at the end, they all call the same function. Let's call that function "wrapUp." Each time wrapUp gets called, you want it to log the name of its caller. How can you do that?
Well, the easiest thing would be to have each of the calling functions pass strings containing their names to wrapUp and have the latter log those parameters. But what if you don't or can't have the functions pass such strings?
Well, back in the olden days, we used to be able to use the "caller" property of the function's prototype. Something like this:
function walk() {
// Do some walking
wrapUp();
}
function bark() {
// Do some barking
wrapUp();
}
function wag() {
// Do some wagging
wrapUp();
}
function wrapUp() {
// Do some wrapping
// Then log who called me
console.log(wrapUp.caller);
}
function test() {
walk(); // [Function: walk]
bark(); // [Function: bark]
wag(); // [Function: wag]
}
But now, according to MDN, this feature is no longer recommended and is, in fact, deprecated. So long, good friend. What are we now to do?
Well, one solution, albeit a tad hacky, is to glean the caller's name from the stack trace:
function wrapUp() {
// Do some wrapping
// Then log who called me
try {
throw new Error('Woof!')
} catch(e) {
const lines = e.stack.split('\n');
const thirdLine = lines[2];
const funcName = thirdLine.match(/at (.*?) \(/)[1];
console.log(`${funcName} called me.`);
}
}
function test() {
walk(); // walk called me.
bark(); // bark called me.
wag(); // wag called me.
}
Above, we purposefully throw an error, but we wrap it in try/catch so as to not disrupt the operation and have access to the stack. We split the trace into lines using the line breaks, and then access the third line. Using a regular expression, we isolate the function name from the string and voila, we have our caller logged. Happy times!