views:

1433

answers:

9

Is it possible to do this:

myfile.js:
function foo() {
    alert(<my-function-name>);
    // pops-up "foo"
    // or even better: "myfile.js : foo"
}

I've got the dojo and jquery frameworks in my stack, so if either of those make it easier, they're available.

+1  A: 

Since you have written a function named foo and you know it is in myfile.js why do you need to get this information dynamically?

That being said you can use arguments.callee.toString() inside the function (this is a string representation of the entire function) and regex out the value of the function name.

Here is a function that will spit out its own name:

function foo() {
    re = /^function\s+([^(]+)/
    alert(re.exec(arguments.callee.toString())[1]);    
}
Andrew Hare
I'm working on an error handler, and I want to report the calling function.
sprugman
+1  A: 

Check this site for learning more about JavaScript stack tracing:

http://eriwen.com/javascript/js-stack-trace/

Bryan Migliorisi
A: 

Try:

alert(arguments.callee.toString());
Deniz Dogan
That would return the entire function as a string
Andy E
+4  A: 

You should be able to get it by using arguments.callee.

You may have to parse out the name though, as it will probably include some extra junk. Though, in some implementations you can simply get the name using arguments.callee.name.

Parsing:

function DisplayMyName() 
{
   var myName = arguments.callee.toString();
   myName = myName.substr('function '.length);
   myName = myName.substr(0, myName.indexOf('('));

   alert(myName);
}

Edit: The code sample above is a slightly-modified copy taken from Javascript - get current function name.

Matt
Actually, actually paying more attention to your question, it sounds like you might want the extra junk :)
Matt
@Matt - If you are going to use an online source please cite it. Your code sample is clearly taken from http://www.tek-tips.com/viewthread.cfm?qid=1209619 and it is unfair to the original author to use it without giving credit.
Andrew Hare
@Andrew - You are right, I should have stated that. It was a quick copy/paste/cleanup of something I already had bookmarked, and an oversight on my part. Thank you for adding it to my post.
Matt
A: 

For non-anonymous functions

function foo()
{ 
    alert(arguments.callee.name)
}

But in case of an error handler the result would be the name of the error handler function, wouldn't it?

fforw
Does that work in IE/JScript?
Andy E
No, does not work with Microsoft JScript.
James Hugard
+2  A: 

This should do it:

var FName = (arguments.callee.toString()).match(/function\s+(\[^\s\(]+)/);
alert(FName[1]);

For the caller, just use caller.toString()

Andy E
A: 

This has to go in the category of "world's ugliest hacks", but here you go.

First up, printing the name of the current function (as in the other answers) seems to have limited use to me, since you kind of already know what the function is!

However, finding out the name of the calling function could be pretty useful for a trace function. This is with a regexp, but using indexOf would be about 3x faster:

function getFunctionName()
{
    var re = /function (.*?)\(/
    var s = getFunctionName.caller.toString();
    var m = re.exec( s )
    return m[1];
}

function Me()
{
    WScript.echo( getFunctionName() )
}

Me();
James Hugard
A: 

Every this comes up someone asks why you'd want to do this - for me the primary purpose is debugging in the field where debugging tools (in a normally non-debugging environment)- when debugging I do a quick find and replace for "){" to "){logFnName()", which I can easily undo when done.

logFnName() will append the results to a logfile which you can monitor, or check after an error to see where the error occurred.

davea0511
A: 

Another use case could be an event dispatcher bound at runtime:

MyClass = function () {
  this.events = {};

  // Fire up an event (most probably from inside an instance method)
  this.OnFirstRun();

  // Fire up other event (most probably from inside an instance method)
  this.OnLastRun();

}

MyClass.prototype.dispatchEvents = function () {
  var EventStack=this.events[GetFunctionName()], i=EventStack.length-1;

  do EventStack[i]();
  while (i--);
}

MyClass.prototype.setEvent = function (event, callback) {
  this.events[event] = [];
  this.events[event].push(callback);
  this["On"+event] = this.dispatchEvents;
}

MyObject = new MyClass();
MyObject.setEvent ("FirstRun", somecallback);
MyObject.setEvent ("FirstRun", someothercallback);
MyObject.setEvent ("LastRun", yetanothercallback);

The advantage here is the dispatcher can be easily reused and doesn't have to receive the dispatch queue as an argument, instead it comes implicit with the invocation name...

In the end, the general case presented here would be "using the function name as an argument so you don't have to pass it explicitly", and that could be useful in many cases, such as the jquery animate() optional callback, or in timeouts/intervals callbacks, (ie you only pass a funcion NAME).

Sampiolin