Is it possible to see the callee/caller of a function when use strict
is enabled?
'use strict'; function jamie (){ console.info(arguments.callee.caller.name); //this will output the below error //uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them }; function jiminyCricket (){ jamie(); } jiminyCricket ();
jamie.name // jamie
. But function names are often irrelevant, other than for debugging, they make no difference in your code, and relying on this functionality for something other than recursion is usually an XY problem.
console.info
so c = console.info
essentially. So when I console something with said function, it just shows in the console that it came from the same place every time. i wanted to output which function called it. Just for my being lazy and cool all rolled into one :D
arguments.callee
and arguments.caller
made certain JS engine optimisations difficult/impossible.
For what it's worth, I agree with the comments above. For whatever problem you're trying to solve, there are usually better solutions.
However, just for illustrative purposes, here's one (very ugly) solution:
'use strict'
function jamie (){
var callerName;
try { throw new Error(); }
catch (e) {
var re = /(\w+)@|at (\w+) \(/g, st = e.stack, m;
re.exec(st), m = re.exec(st);
callerName = m[1] || m[2];
}
console.log(callerName);
};
function jiminyCricket (){
jamie();
}
jiminyCricket(); // jiminyCricket
I've only tested this in Chrome, Firefox, and IE11, so your mileage may vary.
Please note that this should not be used in production. This is an ugly solution, which can be helpful for debugging, but if you need something from the caller, pass it as argument or save it into a accessible variable.
The short version of @p.s.w.g answer(without throwing an error, just instantiating one):
let re = /([^(]+)@|at ([^(]+) \(/g;
let aRegexResult = re.exec(new Error().stack);
sCallerName = aRegexResult[1] || aRegexResult[2];
Full Snippet:
'use strict' function jamie (){ var sCallerName; { let re = /([^(]+)@|at ([^(]+) \(/g; let aRegexResult = re.exec(new Error().stack); sCallerName = aRegexResult[1] || aRegexResult[2]; } console.log(sCallerName); }; function jiminyCricket(){ jamie(); }; jiminyCricket(); // jiminyCricket
([^(]+)
instead of (\w+)
because spaces and punctuation are common.
Error.prototype.stack
property is officially marked as non-standard and implementation-specific.
Error.prototype.stack
documentation on MDN: "Different browsers set this value at different times. For example, Firefox sets it when creating an Error object, while PhantomJS sets it only when throwing the Error, and archived MSDN docs also seem to match the PhantomJS implementation." So p.s.w.g's answer (involving creating, throwing and catching an Error) might be more robust anyway...
It does not worked for me Here is what I finally do, just in case it helps someone
function callerName() {
try {
throw new Error();
}
catch (e) {
try {
return e.stack.split('at ')[3].split(' ')[0];
} catch (e) {
return '';
}
}
}
function currentFunction(){
let whoCallMe = callerName();
console.log(whoCallMe);
}
\w+
are skipped. You should use [^(]+
instead.
You can get a stack trace using:
console.trace()
but this is likely not useful if you need to do something with the caller.
See https://developer.mozilla.org/en-US/docs/Web/API/Console/trace
functionName() {
return new Error().stack.match(/ at (\S+)/g)[1].get(/ at (.+)/);
}
// Get - extract regex
String.prototype.get = function(pattern, defaultValue = "") {
if(pattern.test(this)) {
var match = this.match(pattern);
return match[1] || match[0];
}
return defaultValue; // if nothing is found, the answer is known, so it's not null
}
Success story sharing
new Error().stack