337

How can I access a function name from inside that function?

// parasitic inheritance
var ns.parent.child = function() {
  var parent = new ns.parent();
  parent.newFunc = function() {

  }
  return parent;
}

var ns.parent = function() {
  // at this point, i want to know who the child is that called the parent
  // ie
}

var obj = new ns.parent.child();
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Scott Klarenbach
  • 37,171
  • 15
  • 62
  • 91
  • well, in the parent, i can then access other functions by convention, such as ns[child][schema] or ns[child][dbService]. Without it, I have to hard code these references in every child class. – Scott Klarenbach Apr 15 '10 at 19:45
  • why not just pass the child function as an argument to the parent? var parent = new ns.parent(this); – plodder Apr 15 '10 at 19:50
  • because there are dozens of such lookups, and dozens of children. That is currently what I'm doing, but it's the same every time and would be perfect if that duplicate logic could simply be placed inside the parent once, based on the derived function. – Scott Klarenbach Apr 15 '10 at 19:51
  • see, it's not the child function I want, it's the naming convention used, because that naming convention can be used to load other functions that are not currently defined on the child object, but are related to that child throughout the system. – Scott Klarenbach Apr 15 '10 at 19:53
  • ie, app.schemas.child = { } which is defined in another file and not present on the child object. – Scott Klarenbach Apr 15 '10 at 19:54
  • 1
    @Scott `var ns.parent.child` - this code is invalid – Šime Vidas Apr 03 '11 at 20:01
  • @Scott, there is a lot going on here. Why do you need a reference back to the caller? Would it not be easier to send the reference while making the call? – jbcurtin Apr 03 '11 at 20:34
  • what would you return if your function was defined as `foo = bar = function() { return function_name(); }`? – Gareth Apr 03 '11 at 20:53
  • 1
    @Scott I agree with everyone else, your managing your complexity and code structure wrong to need to do this. This kind of hard-coupling is a bad design decision and is going to make a mess. @SimeVidas your a great necromancer :) – Raynos Apr 03 '11 at 21:01
  • It strikes me has something odd, because if I do something like var test2 = test; What is the name of the function now? – Claudio Apr 21 '14 at 20:48
  • Possible duplicate of [Can I get the name of the currently running function in JavaScript?](https://stackoverflow.com/questions/1013239/can-i-get-the-name-of-the-currently-running-function-in-javascript) – Michael Freidgeim May 11 '19 at 23:27
  • Does this answer your question? [Get current function name in strict mode](https://stackoverflow.com/questions/38435450/get-current-function-name-in-strict-mode) – Michael Freidgeim Sep 26 '20 at 01:48

22 Answers22

204

In ES6, you can just use myFunction.name.

Note: Beware that some JS minifiers might throw away function names, to compress better; you may need to tweak their settings to avoid that.

In ES5, the best thing to do is:

function functionName(fun) {
  var ret = fun.toString();
  ret = ret.substr('function '.length);
  ret = ret.substr(0, ret.indexOf('('));
  return ret;
}

Using Function.caller is non-standard. Function.caller and arguments.callee are both forbidden in strict mode.

Edit: nus's regex based answer below achieves the same thing, but has better performance!

Michael Freidgeim
  • 26,542
  • 16
  • 152
  • 170
Vlad A. Ionescu
  • 2,638
  • 1
  • 16
  • 19
  • 1
    While this didn't answer the question sufficiently for me (due to anonymous functions), it did give me idea to do this: `fun.toString().substr(0, 100)` which for my needs will be enough to locate the function in question. So, thanks for the inspiration! – Campbeln Jul 07 '15 at 03:22
  • 1
    Nice, ES6 `myFunction.name` is perfect. Is this a preferred thing to do in ES6? – djskinner Nov 17 '15 at 10:37
  • 4
    Yup `myFunction.name` is the best thing to do in ES6. – Vlad A. Ionescu Nov 17 '15 at 17:41
  • 1
    NB. myFunction.name also works with ES6 arrow functions (usually anonymous), if you assign them in an expression (e.g. `const myNamedFunction = () => { ...};`). Thanks @hughfdjackson: http://stackoverflow.com/a/31544156/396246 – poshaughnessy Feb 22 '16 at 12:40
  • 59
    What's the point in `myFunction.name` if you type the function name? defeats the purpose of magic variables. – adi518 Mar 23 '18 at 23:55
  • 9
    @adi518: not necessarily .. suppose you have any array of functions and you iterating over it, using for/foreach ..then `arr[index].name` will also work :) – Debasish Chowdhury Nov 25 '18 at 04:42
  • 1
    Or maybe even `fun.toString().split('(')[0].split(' ')[1]` or even shorter `fun.toString().split(/[\(\s]/)[1]` – Joe DF Oct 29 '19 at 18:10
  • 5
    @adi518 It's not useless. If I'm renaming the function within my IDE, `myFunction.name` will also be updated. Sure, intelliJ supports renaming identifiers within strings, but that works a lot less consistently and will silently become outdated if somebody forgets to tick the "search in strings" option. `myFunction.name` is a slightly better choice than hardcoding the string. – byxor Dec 04 '19 at 11:49
180

ES6 (inspired by sendy halim's answer below):

myFunction.name

Explanation on MDN. As of 2015 works in nodejs and all major browsers except IE.

Note: On bound functions this will give "bound <originalName>". You will have to strip the "bound " if you want to get the original name.


ES5 (inspired by Vlad's answer):

If you have a reference to the function, you can do:

function functionName( func )
{
    // Match:
    // - ^          the beginning of the string
    // - function   the word 'function'
    // - \s+        at least some white space
    // - ([\w\$]+)  capture one or more valid JavaScript identifier characters
    // - \s*        optionally followed by white space (in theory there won't be any here,
    //              so if performance is an issue this can be omitted[1]
    // - \(         followed by an opening brace
    //
    var result = /^function\s+([\w\$]+)\s*\(/.exec( func.toString() )

    return  result  ?  result[ 1 ]  :  '' // for an anonymous function there won't be a match
}
  • I have not run unit tests on this, or verified implementation differences, but in principle it should work, if not leave a comment.
  • Note: won't work on bound functions
  • Note: that caller and callee are considered deprecated.

[1] I include it here because it is legal and often enough syntax highlighting tools fail to take into account the white space between function name and parenthesis. On the other hand, I'm not aware of any implementation of .toString() that will include white space here, so that's why you can omit it.


As an answer to the original question, I would drop parasitic inheritance and go for some more traditional OOP design patterns. I wrote a TidBits.OoJs to comfortably write OOP code in JavaScript with a feature set mimicking C++ (not yet complete, but mostly).

I see from the comments that you would like to avoid passing information parent needs to it's constructor. I must admit that traditional design patterns won't save you from that one though, since it is generally a considered a good thing to make your dependencies obvious and enforced.

I would also suggest to steer away from anonymous functions. They only make debugging and profiling a PITA because everything just shows up as "anonymous function", and there is no benefit to them that I'm aware of.

  • 6
    Nice RegEx! Here's a performance test showing that your code is the fastest in many cases. In general it seems that RegEx beats native JS by around 2x speed here on average. http://jsperf.com/get-function-name/2 – Beejor May 26 '15 at 05:43
  • 1
    @Tomasz Hi, thanks for pointing that out. I didn't know that. A bound function is actually a new function that wraps your original function. The ecmascript standard § 19.2.3.2 defines that the name of the new function shall be "bound" + originalName. The toString method won't work on bound functions either... You will have to strip the word bound. –  Jan 26 '17 at 11:28
  • 1
    What's the point in myFunction.name if you type the function name? defeats the purpose of magic variables. – Borjovsky Sep 14 '18 at 12:58
  • 1
    Note that if you're using React Native this may not work properly. I have a RN project I'm working on with expo version 36 and a component method's `.name` property was showing up as the string "value", no matter what it was called. Weirdly enough, while testing in the expo app it was fine, however, once compiled into a real application, it would crash silently. – Andy Corman Mar 09 '20 at 17:51
89

what you're doing is assigning unnamed function to a variable. you probably need named function expression instead ( http://kangax.github.com/nfe/ ).

var x = function x() {
    console.log( arguments.callee.name );
}
x();

however I'm not sure how much cross-browser that is; there's an issue with IE6 that makes you function's name leak to the outer scope. also, arguments.callee is kind of deprecated and will result in error if you're using strict mode.

wildcard
  • 7,353
  • 3
  • 27
  • 25
26

It looks like the most stupid thing, that I wrote in my life, but it's funny :D

function getName(d){
  const error = new Error();
  const firefoxMatch = (error.stack.split('\n')[0 + d].match(/^.*(?=@)/) || [])[0];
  const chromeMatch = ((((error.stack.split('at ') || [])[1 + d] || '').match(/(^|\.| <| )(.*[^(<])( \()/) || [])[2] || '').split('.').pop();
  const safariMatch = error.stack.split('\n')[0 + d];

  // firefoxMatch ? console.log('firefoxMatch', firefoxMatch) : void 0;
  // chromeMatch ? console.log('chromeMatch', chromeMatch) : void 0;
  // safariMatch ? console.log('safariMatch', safariMatch) : void 0;
  
  return firefoxMatch || chromeMatch || safariMatch;
}

d - depth of stack. 0 - return this function name, 1 - parent, etc.;
[0 + d] - just for understanding - what happens;
firefoxMatch - works for safari, but I had really a little time for testing, because mac's owner had returned after smoking, and drove me away :'(

Testing:

function limbo(){
  for(let i = 0; i < 4; i++){
    console.log(getName(i));
  }
}
function lust(){
  limbo();
}
function gluttony(){
  lust();
}

gluttony();

Result:
Chrome:
enter image description here

Fitefox:
enter image description here

This solution was creating only just for fun! Don't use it for real projects. It does not depend on ES specification, it depends only on browser realization. After the next chrome/firefox/safari update it may be broken.
More than that there is no error (ha) processing - if d will be more than stack length - you will get an error;
For other browsers error's message pattern - you will get an error;
It must work for ES6 classes (.split('.').pop()), but you sill can get an error;

Justine M.
  • 359
  • 8
  • 24
user3335966
  • 2,673
  • 4
  • 30
  • 33
23

Any constructor exposes a property name, which is the function name. You access the constructor via an instance (using new) or a prototype:

function Person() {
  console.log(this.constructor.name); //Person
}

var p = new Person();
console.log(p.constructor.name); //Person

console.log(Person.prototype.constructor.name);  //Person
roland
  • 7,695
  • 6
  • 46
  • 61
18

This might work for you:

function foo() { bar(); }

function bar() { console.log(bar.caller.name); }

running foo() will output "foo" or undefined if you call from an anonymous function.

It works with constructors too, in which case it would output the name of the calling constructor (eg "Foo").

More info here: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller

They claim it's non-standard, but also that it's supported by all major browsers: Firefox, Safari, Chrome, Opera and IE.

Hunter Fernandes
  • 1,287
  • 13
  • 14
Jacob Mouka
  • 2,005
  • 18
  • 26
10

You can't. Functions don't have names according to the standard (though mozilla has such an attribute) - they can only be assigned to variables with names.

Also your comment:

// access fully qualified name (ie "my.namespace.myFunc")

is inside the function my.namespace.myFunc.getFn

What you can do is return the constructor of an object created by new

So you could say

var obj = new my.namespace.myFunc();
console.info(obj.constructor); //my.namespace.myFunc
plodder
  • 2,304
  • 18
  • 19
  • 1
    i need it inside the func because i'm passing it up the inheritance chain and I omitted that stuff for brevity. – Scott Klarenbach Apr 15 '10 at 19:30
  • 1
    'this' will be the instance that invoked the function. So if you 'this' inside the parent function that will give you the instance of the function that called it. That's all you should need - not sure why you need the name too – plodder Apr 15 '10 at 19:47
  • 1
    well, in the parent, i can then access other functions by convention, such as ns[child][schema] or ns[child][dbService]. Without it, I have to hard code these references in every child class. – Scott Klarenbach Apr 15 '10 at 19:49
  • 1
    my use case for finding the name is to make it easier for constructing console.error messages that tell where the message came from without having to revert to the stack dump. e.g. console.error({'error':{self.name reference} + " error with input parameter"). It becomes much easier to cut/paste error messages that repeat in multiple functions if you don't have to stop and change text within them each time. In my case, I'm returning promise errors from multiple promise calls - nice to know what promise/function generated the error. – Scott Sep 26 '19 at 18:25
10

You could use this, for browsers that support Error.stack (not nearly all, probably)

function WriteSomeShitOut(){ 
  var a = new Error().stack.match(/at (.*?) /);
  console.log(a[1]);
} 
WriteSomeShitOut();

of course this is for the current function, but you get the idea.

happy drooling while you code

noripcord
  • 3,412
  • 5
  • 29
  • 26
8

You could use Function.name:

In most implementations of JavaScript, once you have your constructor's reference in scope, you can get its string name from its name property (e.g. Function.name, or Object.constructor.name

You could use Function.callee:

The native arguments.caller method has been deprecated, but most browsers support Function.caller, which will return the actual invoking object (its body of code): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fcaller

You could create a source map:

If what you need is the literal function signature (the "name" of it) and not the object itself, you might have to resort to something a little more customized, like creating an array reference of the API string values you'll need to access frequently. You can map them together using Object.keys() and your array of strings

Benny Schmidt
  • 3,230
  • 1
  • 19
  • 14
7

You can use name property to get the function name, unless you're using an anonymous function

For example:

var Person = function Person () {
  this.someMethod = function () {};
};

Person.prototype.getSomeMethodName = function () {
  return this.someMethod.name;
};

var p = new Person();
// will return "", because someMethod is assigned with anonymous function
console.log(p.getSomeMethodName());

now let's try with named function

var Person = function Person () {
  this.someMethod = function someMethod() {};
};

now you can use

// will return "someMethod"
p.getSomeMethodName()
sendy halim
  • 405
  • 4
  • 11
6

as part as ECMAScript 6 you can use Function.name method

function doSomething() {}

alert(doSomething.name); // alerts "doSomething"
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
pleerock
  • 18,322
  • 16
  • 103
  • 128
6

You can use constructor name like:

{your_function}.prototype.constructor.name

this code simply return name of a method.

3

I know this is a old question but lately I've been facing some similar issue while trying to decorate some React Component's methods, for debugging purposes. As people already said, arguments.caller and arguments.callee are forbidden in strict mode which is probably enabled by default in your React transpiling. You can either disable it, or I've been able to come up with another hack, because in React all class functions are named, you can actually do this:

Component.prototype.componentWillMount = function componentWillMount() {
    console.log('Callee name: ', this.__proto__.constructor.toString().substr(0,30));
...
}
weisk
  • 2,468
  • 1
  • 18
  • 18
  • 1
    Note that Object.prototype.__proto__ is Deprecated https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto – Michael Freidgeim Jul 11 '21 at 02:34
3

A simple solution to dynamically retrieve function names [like magic variables] is the use of scoped variables.

{
  function parent() {
    console.log(a.name);
  }; let a = parent
}
{
  function child() {
    console.log(a.name)
  }; let a = child
};

parent();//logs parent
child();//logs child

Note: Nested functions cease to be source elements, and are hence not hoisted. Also, this technique cannot work with anonymous functions.

Eazicoding
  • 191
  • 9
2

I had a similar problem and I solved it as follows:

Function.prototype.myname = function() {
   return this.toString()
       .substr( 0, this.toString().indexOf( "(" ) )
       .replace( "function ", "" ); 
}

This code implements, in a more comfortable fashion, one response I already read here at the top of this discussion. Now I have a member function retrieving the name of any function object. Here's the full script ...

<script language="javascript" TYPE="text/javascript">

    Function.prototype.myname = function() { 
        return this.toString()
            .substr( 0, this.toString().indexOf( "(" ) )
            .replace("function ", "" ); 
    }
    function call_this( _fn ) { document.write( _fn.myname() ); }
    function _yeaaahhh() { /* do something */ }
    call_this( _yeaaahhh ); 

</script>
mariowise
  • 2,167
  • 2
  • 21
  • 34
Sandro Rosa
  • 507
  • 4
  • 12
2

This worked for me.

function AbstractDomainClass() {
    this.className = function() {
        if (!this.$className) {
            var className = this.constructor.toString();
            className = className.substr('function '.length);
            className = className.substr(0, className.indexOf('('));
            this.$className = className;
        }
        return this.$className;
    }
}

Test code:

var obj = new AbstractDomainClass();
expect(obj.className()).toBe('AbstractDomainClass');
2

If I understood what you wanted to do, this is what I do inside a function constructor.

if (!(this instanceof arguments.callee)) {
    throw "ReferenceError: " + arguments.callee.name + " is not defined";
}
Zibri
  • 9,096
  • 3
  • 52
  • 44
2

This will work in ES5, ES6, all browsers and strict mode functions.

Here's how it looks with a named function.

(function myName() {
  console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at myName (<anonymous>:2:15)

Here's how it looks with an anonymous function.

(() => {
  console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at <anonymous>:2:15
Eric Rini
  • 1,830
  • 15
  • 20
  • 1
    This produces different results per browser. Chrome: `at myName (:2:15)` Firefox: `@debugger eval code:3:3` – jkdev Jan 02 '20 at 22:10
  • 2
    (function myName() { console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim().split(" ")[1]); })(); – Zibri Feb 01 '20 at 13:44
  • 1
    Similar to https://stackoverflow.com/questions/38435450/get-current-function-name-in-strict-mode/38435618#38435618 – Michael Freidgeim Jul 11 '21 at 02:06
1

Just try Function.name

const func1 = function() {};

const object = {
  func2: function() {}
};

console.log(func1.name);
// expected output: "func1"

console.log(object.func2.name);
// expected output: "func2"
Ashwani Panwar
  • 3,819
  • 3
  • 46
  • 66
  • The question was : "How to get the function name from within that function?" In this answer function name is known and it checked from outside of function. – Ali javanmardi Jan 08 '23 at 18:04
-2

look here: http://www.tek-tips.com/viewthread.cfm?qid=1209619

arguments.callee.toString();

seems to be right for your needs.

Manuel Bitto
  • 5,073
  • 6
  • 39
  • 47
-2

Easy way to get function name from within fuction you are running.

function x(){alert(this.name)};x()
Dave Brown
  • 923
  • 9
  • 6
  • 2
    gives me a GUID – Tamir Daniely Jun 17 '18 at 04:22
  • 2
    be aware to the content of `this` it basically can be anything. try `(function(){console.log(this.name);}).bind({name: "put basically anything here even an object maybe a 1TB string maybe a class definition"})()` – Valen May 18 '19 at 22:38
-2

you can use Error.stack to trace the function name and exact position of where you are in it.

See stacktrace.js

kofifus
  • 17,260
  • 17
  • 99
  • 173