9

I'm trying to get the name of the currently running function. From what I've read, this should be possible using:

(arguments.callee.toString()).match(/function\s+(\[^\s\(]+)/)

However, when I run this in Firefox and Safari (latest versions on Mac) the name is not returned.

console.log( arguments.callee ) returns the source of the function, but not the assigned name. arguments.callee.name returns an empty string.

My sample code is as follows:

var testobj = {
    testfunc: function(){
        console.log( (arguments.callee.toString()).match(/function\s+(\[^\s\(]+)/) );
    }
}
testobj.testfunc();
Geuis
  • 41,122
  • 56
  • 157
  • 219
  • Can I ask, why do you want/need to do this? – James Dec 20 '09 at 11:19
  • Yah. So I'm working on a pet project involving function chaining. I have about 50 different functions that all run the same code, except that a particular variable in them is defined as the same name of the function. I want to reduce all of the duplication to a single function that detects the name of the calling function and uses that name as the variable that's currently hard coded. With this method, I can define all of my functions in a single line. – Geuis Dec 20 '09 at 11:32
  • 2
    `toString()` ing functions like this (aka function "decompilation") has its warts. See http://perfectionkills.com/those-tricky-functions/, http://perfectionkills.com/detecting-built-in-host-methods/, http://my.opera.com/hallvors/blog/show.dml/1665828 and http://my.opera.com/hallvors/blog/2007/07/07/prototype-findorstore-considered-harmful – Crescent Fresh Dec 20 '09 at 14:02
  • 3
    I have to say I'm pretty disappointed by the utterly piss poor answers to this question, none of them seem like they were tested whatsoever – Dexygen Feb 12 '10 at 21:06

8 Answers8

11

You declared an anonymous function with

function(){

You should declare it as

function testfunc(){

to get the name printed.

Eric Bréchemier
  • 1,908
  • 3
  • 18
  • 30
  • 5
    Be aware that named function expressions (which is what you're suggesting) behave oddly in IE. See http://yura.thinkweb2.com/named-function-expressions/ – Tim Down Dec 20 '09 at 15:43
  • To clarify: in the case of the object style above that would be `{ testfunc: function testfunc() { ...`. This is also nice to do when debugging things in the browser, helps the debugger help you see which function you have problems in. – clacke Jul 30 '10 at 09:39
  • According to the Wayback Machine, the link in @TimDown 's comment redirects to http://kangax.github.com/nfe/ before the domain name expired – Phil Jan 22 '15 at 09:17
8

The typical arguments.callee hacks don't work here because what you've done is assigned an anonymous function as the value for the object's 'testfunc' key. In this case the hacking even gets worse, but it can be done, as follows:

var testobj = {
    testfunc: function(){
      for (var attr in testobj) {
              if (testobj[attr] == arguments.callee.toString()) {
                  alert(attr);
                  break;
                }
            }
    }
}
testobj.testfunc();
Dexygen
  • 12,287
  • 13
  • 80
  • 147
3

On firefox 3.5, Safari 5, and Chrome 6.0 you can use:

function myFunctionName() {
 alert("Name is " + arguments.callee.name );
}

myFunctionName();

You can also get the function that called the current one using arguments.callee.caller.

Ben Clayton
  • 80,996
  • 26
  • 120
  • 129
2
Function.prototype.getName = function(fn) {
    if(Function.name || Function.prototype.name) return this.name;
    return this.toString().match(/^function\s+(\w+)\s*\(/)[1];
};
yckart
  • 32,460
  • 9
  • 122
  • 129
2
/function\s+(\[^\s\(]+)/

What's with the backslash before [? I don't think you want a literal square bracket here. Without that it should work.

Although I'd strongly recommend against anything to do with sniffing function name or especially sniffing caller function. Almost anything you might do using these hideous hacks will be better done using some combination of closures and lookups.

bobince
  • 528,062
  • 107
  • 651
  • 834
2

I think there's a much cleaner and elegant solution to all this. Assuming the function is a member of some higher-level object—and that's always going to be the case, even if the function's owner is "window" or some other global object, we can access the global object via the this keyword, we can access the function itself via arguments.callee and we can access all the parent's object (function) names via for (var o in this), so you should be able to get the desired information fairly easily as...

returnMyName = function() {
  for (var o in this) {
    if (arguments.callee===this[o]) return o;
  }
};

That should be robust and avoid any weird IE browser behaviors accessing named functions, etc.

0

First of all, the function doesn't have a name. The function name is what you put in-between function and the arguments list (...). Here's how to get a function's name (don't use the name property, as it can be changed):

var fName = arguments.callee.toString(0).match(
  /^function\s*(?:\s+([\w\$]*))?\s*\(/
);
fName = (fName ? fName[1] : "");
Eli Grey
  • 35,104
  • 14
  • 75
  • 93
0

I found that if you simply log the function object, like so:

console.log(arguments.callee)

or

console.debug(arguments.callee)

that you simply get the function name in the console log with some options.

Dave Van den Eynde
  • 17,020
  • 7
  • 59
  • 90