40

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?

Community
  • 1
  • 1
Gili
  • 86,244
  • 97
  • 390
  • 689

8 Answers8

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];
    }
  });
}
Gili
  • 86,244
  • 97
  • 390
  • 689
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • 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)`? – gdoron May 16 '12 at 18:27
  • Why it doesn't match `foo){...`? – gdoron May 16 '12 at 19:54
  • 1
    @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. – Phrogz May 16 '12 at 19:57
  • This relies on `this` referring to the function object. That's not always the case though! foo.bar() -> `this` === foo for example. –  Jul 26 '13 at 19:24
  • 1
    modified a bit not to include spaces: /function ([^(\s]*)/ – VuesomeDev Oct 02 '13 at 15:18
21
var name = callback.name;

MDN:

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

Live DEMO

Community
  • 1
  • 1
gdoron
  • 147,333
  • 58
  • 291
  • 367
  • 1
    `[the name] property is not standard` is no longer true, it's in ECMA 6.0 / 2015: http://www.ecma-international.org/ecma-262/6.0/#sec-setfunctionname / Also see http://www.2ality.com/2015/09/function-names-es6.html – CodeManX Apr 08 '16 at 10:39
6
function bar(callback){
    var name=callback.toString();
    var reg=/function ([^\(]*)/;
    return reg.exec(name)[1];
}

>>> function foo() { };
>>> bar(foo);
"foo"
>>> bar(function(){});
""
kojiro
  • 74,557
  • 19
  • 143
  • 201
  • More elegant regex than mine; nice :) Are you certain that all browsers will place a space after the leading `function`? – Phrogz May 16 '12 at 18:13
  • @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. – kojiro May 16 '12 at 18:27
  • Having seen your code I recall looking at the spec long ago for the normalized string representation and IIRC the space is required. – Phrogz May 16 '12 at 18:40
2
var x = function fooBar(){};
console.log(x.name);
// "fooBar"
osahyoun
  • 5,173
  • 2
  • 17
  • 15
2

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"
David Fooks
  • 1,063
  • 10
  • 10
  • This will probably work, but isn't it much more expensive to construct a stack-trace than to parse `this.toString()`? – Gili Oct 30 '14 at 19:28
  • Yeah, but I'm only using this for debug messages. The above answers would only return "hi" this returns "MyObject.hi". – David Fooks Nov 07 '14 at 15:59
  • 1
    That is really nice for debugging. Thanks or sharing! – Raisch Feb 16 '17 at 13:56
1

try to access the .name property:

callback.name 
JMax
  • 26,109
  • 12
  • 69
  • 88
Tiago Peczenyj
  • 4,387
  • 2
  • 22
  • 35
0

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

var a = document.form1
a.onsubmit.name
Pipe2290
  • 1
  • 1
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];
    }
  });
}