42

I want to do the opposite of Get JavaScript function-object from its name as a string?

That is, given:

function foo()
{}

function bar(callback)
{
  var name = ???; // how to get "foo" from callback?
}

bar(foo);

How do I get the name of the function behind a reference?

4
  • var bat = foo; bar(bat) - now what should it print? Commented May 16, 2012 at 18:03
  • 2
    @Alnitak. It should print foo. that's the function name. bat is a variable with a reference to the foo function. Commented May 16, 2012 at 18:06
  • 1
    what happens if the callback doesn't have a name? -- ie bar(function() {...}); Commented May 16, 2012 at 21:21
  • 1
    @Spudley: ideally, the code should throw an exception stating that anonymous functions are not supported. Commented May 17, 2012 at 1:03

9 Answers 9

31

If you can't use myFunction.name then you can:

// Add a new method available on all function values
Function.prototype.getName = function(){
  // Find zero or more non-paren chars after the function start
  return /function ([^(]*)/.exec( this+"" )[1];
};

Or for modern browsers that don't support the name property (do they exist?) add it directly:

if (Function.prototype.name === undefined){
  // Add a custom property to all function values
  // that actually invokes a method to get the value
  Object.defineProperty(Function.prototype,'name',{
    get:function(){
      return /function ([^(]*)/.exec( this+"" )[1];
    }
  });
}
Sign up to request clarification or add additional context in comments.

5 Comments

Ohhh, now I got it, the ( if for the exec match, not a part of the regex. cool. +1. BTW, why it doesn't alert foo)?
Why it doesn't match foo){...?
@gdoron Because regex must match characters sequentially until it stops. The function in the regex starts it matching, and then it consumes zero or more anything-but-a-( characters (as many as possible). Once it has done that, it must stop; it can't "skip over" non-matches and continue on.
This relies on this referring to the function object. That's not always the case though! foo.bar() -> this === foo for example.
modified a bit not to include spaces: /function ([^(\s]*)/
24
var name = callback.name;

MDN:

The name property returns the name of a function, or an empty string for anonymous functions:

Live DEMO

1 Comment

[the name] property is not standard is no longer true, it's in ECMA 6.0 / 2015: ecma-international.org/ecma-262/6.0/#sec-setfunctionname / Also see 2ality.com/2015/09/function-names-es6.html
6
function bar(callback){
    var name=callback.toString();
    var reg=/function ([^\(]*)/;
    return reg.exec(name)[1];
}

>>> function foo() { };
>>> bar(foo);
"foo"
>>> bar(function(){});
""

3 Comments

More elegant regex than mine; nice :) Are you certain that all browsers will place a space after the leading function?
@Phrogz I'm confident enough not to change the above. If there is an edge case, it would only affect the anonymous function anyway, and bar could easily be adjusted to take that into account.
Having seen your code I recall looking at the spec long ago for the normalized string representation and IIRC the space is required.
2
var x = function fooBar(){};
console.log(x.name);
// "fooBar"

Comments

1

try to access the .name property:

callback.name 

Comments

1

You can extract the object and function name with:

function getFunctionName()
{
    return (new Error()).stack.split('\n')[2].split(' ')[5];
}

For example:

function MyObject()
{
}

MyObject.prototype.hi = function hi()
{
    console.log(getFunctionName());
};

var myObject = new MyObject();
myObject.hi(); // outputs "MyObject.hi"

3 Comments

This will probably work, but isn't it much more expensive to construct a stack-trace than to parse this.toString()?
Yeah, but I'm only using this for debug messages. The above answers would only return "hi" this returns "MyObject.hi".
That is really nice for debugging. Thanks or sharing!
0

If you were looking for the function on an specific object event, this may help:

var a = document.form1
a.onsubmit.name

Comments

0

for me, with just a little modification (adding \ before parent), this work:

if (Function.prototype.name === undefined){
  // Add a custom property to all function values
  // that actually invokes a method to get the value
  Object.defineProperty(Function.prototype,'name',{
    get:function(){
      return /function ([^\(]*)/.exec( this+"" )[1];
    }
  });
}

Comments

-1

I think the answer is simpler than most of these. If the function is

function func() {}

then the name of the function as a string is func.toString() .

If the function is unnamed, then you would have to find the name of the variable or constant that stores its name (which depends on the program code).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.