I need the current function name as a string to log to our log facility. But arguments.callee.name only works in loose mode. How to get the function name under "use strict"?
 
    
    - 32,014
- 33
- 141
- 226
- 
                    2If you are able to modify the function's body to add logging code, can't you just hard-code the function name? What advantage would you have if you could read it from a property? – nnnnnn Jul 18 '16 at 11:36
- 
                    9@nnnnnn someone keeps renaming functions but forgets to update the log line. – exebook Jul 18 '16 at 11:44
- 
                    did you find a nice solution for it? creating an Error object may have a performance impact, so, I'm keep looking the nice way to get the function name. – Kostanos May 11 '22 at 05:14
- 
                    @Kostanos not directly, but a workaround for that particular case what was to type `log('^FUNAME^')` instead and then use my own tiny parser on production that would replace ^FUNAME^ with a current function name which is found after the preceeding word `function`. – exebook May 22 '22 at 16:46
7 Answers
For logging/debugging purposes, you can create a new Error object in the logger and inspect its .stack property, e.g.
function logIt(message) {
    var stack = new Error().stack,
        caller = stack.split('\n')[2].trim();
    console.log(caller + ":" + message);
}
function a(b) {
    b()
}
a(function xyz() {
    logIt('hello');
}); 
    
    - 211,518
- 52
- 313
- 390
- 
                    
- 
                    A great answer @georg. Note that ``[2]`` is relative to this example only, if you have for example a stack containing three parent functions in this case we must change **2** to **3** – ismnoiet Jul 18 '16 at 12:40
- 
                    5@hamism: `stack[2]` is always the function that called the logger, no matter how deep the stack is. – georg Jul 18 '16 at 17:59
- 
                    
- 
                    3It is a clever solution for logging/debugging. To anyone else considering using this in production code though (in my case, for event tracking), be warned: *"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."* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack) – evanrmurphy Oct 08 '18 at 01:03
You can bind function as its context then you can access its name via this.nameproperty:
function x(){
  console.log(this.name);
}
x.bind(x)();
 
    
    - 6,424
- 11
- 43
- 76
- 
                    1
- 
                    This is clever, but the effect of bind is permanent, and the value of this cannot be changed again, which can cause bugs. Perharps, x.call(x) might be a better solution – Eazicoding Jul 25 '21 at 16:02
- 
                    @Eazicoding binding does not affect the original function reference. `bind()` creates a copy of the function with the new context. – seebiscuit Jun 27 '23 at 17:49
After little research here is a good solution :
function getFnName(fn) {
  var f = typeof fn == 'function';
  var s = f && ((fn.name && ['', fn.name]) || fn.toString().match(/function ([^\(]+)/));
  return (!f && 'not a function') || (s && s[1] || 'anonymous');
}
function test(){
    console.log(getFnName(this));
}
test  = test.bind(test);
test(); // 'test'
 
    
    - 4,129
- 24
- 30
- 
                    6But that doesn't work from within the function unless you already have a reference to the function. OP asked for a replacement for `arguments.callee.name`... – nnnnnn Jul 18 '16 at 11:32
Building on @georg solution, this one returns just the function name. Note though that it may fail if called from an anonymous function
function getFncName() {
    const stackLine = (new Error())!.stack!.split('\n')[2].trim()
    const fncName = stackLine.match(/at Object.([^ ]+)/)?.[1]
    return fncName
}
function Foo() {
    console.log(getFncName()) // prints 'Foo'
}
 
    
    - 1,251
- 11
- 17
A simple solution to dynamically retrieve function names [like magic variables] is the use of scoped variables, and the Function.name property.
{
  function foo() {
    alert (a.name);
  }; let a = foo
}
{
  function foo2() {
    alert(a.name)
  }; let a = foo2
};
foo();//logs foo
foo2();//logs foo2
Note: Nested functions cease to be source elements, and are hence not hoisted. Also, this technique cannot work with anonymous functions.
 
    
    - 191
- 9
If (like me) you want to define this elsewhere and call it generically, you can store the code as a string somewhere global or import it, then eval() it wherever to access the current function name. (Using eval keeps the context at the point of invocation.)
There's gotta be a way to do this without using a string, but whatever.
SomeObject.whatFunc =
  'const s = new Error().stack;' +
  "const stackLine = new Error().stack.split('\\n')[2].trim();" +
  'const fncName = stackLine.match(/(?<=at )(.*)(?= \\()/gm)[0];' +
  'console.log(fncName);'
// Whereever you want the func name
function countBananas('weeee') {
  eval(SomeObject.whatFunc)
  // blah blah blah
}
countBananas() // logs 'countBananas'
 
    
    - 394
- 1
- 4
just an update to get the full name :
function logIt(message) {
    var stack = new Error().stack,
    //  update is on this line
    caller = stack.split('\n')[2].trim().split(/\s+/)[1];
    console.log(caller.trim().split(/\s+/)[1];);
}
function a(b) {
  b()
}
a(function xyz() {
  logIt('hello');
});
