52

Does anyone know if there is a way to get JavaScript function name. For example I got a function like

function test1(){
alert(1);
}

I have it in my head section. Then I create an object obj1 and put my function there

obj1.func = test1;

When I call a method in obj1 object, do I have any way to get my function name (test1) inside of this method, except parsing the source (this.func.toString()) of the function.

informatik01
  • 16,038
  • 10
  • 74
  • 104
kalan
  • 1,752
  • 4
  • 20
  • 35

7 Answers7

68
function test() {  alert(arguments.callee.name); } 
b = test; 
b();

outputs "test" (in Chrome, Firefox and probably Safari). However, arguments.callee.name is only available from inside the function.

If you want to get name from outside you may parse it out of:

b.toString();

but I think name property of function object might be what you need:

alert(b.name);

this however does not seem work for IE and Opera so you are left with parsing it out manually in those browsers.

Nate Anderson
  • 18,334
  • 18
  • 100
  • 135
Kamil Szot
  • 17,436
  • 6
  • 62
  • 65
  • 13
    Two things, this is both [deprecated](https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments/callee) and doesn't work in IE, even IE8 :) – Nick Craver Jul 05 '10 at 11:01
  • 1
    @Nick Craver: `callee` was deprecated as a property of `Function.arguments`, but retained as a property of `arguments`: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Functions/arguments – Daniel Trebbien Jul 05 '10 at 11:05
  • @Nick Craver: I'm not sure why this wouldn't work in IE 8, because MSDN claims that `callee` has been available since JScript 5.5 (shipped with IE 5.5): http://msdn.microsoft.com/en-us/library/334e1zza(VS.85).aspx – Daniel Trebbien Jul 05 '10 at 11:08
  • @Daniel - First, good point about the function distinction. For the second, `JScript 5.5 != JavaScript 1.5`, it never has...but you don't have to take my word for it. Open IE8 and test it yourself: http://jsfiddle.net/guxRA/ – Nick Craver Jul 05 '10 at 11:11
  • 1
    @Nick: Oh, I know that JScript 5.5 does not implement Javascript 1.5. I was just wondering why `arguments.callee.name` wouldn't work in IE 5.5+. I tested it the code in IE 6. Indeed, it doesn't work. I then tested http://jsfiddle.net/guxRA/2/ and it appears that IE 6 produces the source code for the function as `arguments.callee`. How funny. – Daniel Trebbien Jul 05 '10 at 11:22
  • @Daniel - Yup, good 'ol IE...not sure why this is getting up-voted, as it's not a viable solution to the problem, not unless you intend to ignore a very large audience. I understand if it doesn't work in IE6, I even smile a little, but IE7 and IE8 I don't think you can ignore. – Nick Craver Jul 05 '10 at 11:24
  • 12
    More to the point, the non-standard `name` property of `Function` objects is not supported in IE. – Tim Down Jul 05 '10 at 11:30
  • Parse it out of arguments.callee.toString(). Afaik the only way to define a named function in Javascript is by preceding the name with the keyword 'function', so probably a simple indexOf will get you a long way there. – Stijn de Witt Jul 23 '13 at 23:06
  • This worked for me onlt when i did `var _ = function(){}`, but not a `function _()[}`. UPD: oh no, the opposite. – Nakilon Nov 07 '13 at 03:09
  • 1
    @Nakilon - when you do var _ = function(){} you create anonymous (nameless) function and assign it to the variable named _. Function cannot know or remember that it was assigned to the variable of that name so checking the name of the function gives you nothing. – Kamil Szot Nov 07 '13 at 13:01
  • 3
    FYI function.name is "part of the ECMAScript 2015 (ES6) standard", so it should be future proof (but may not work everywhere today). See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name – user276648 Sep 08 '15 at 03:38
11

Until ES2015, there was no standard way to get the name of a function. Most current browsers support a name property on Function objects that was non-standard until ES2015, but no current version of IE does. The only option this leaves you if you need to support IE is trying to parse the name from the function's string representation, which is not a good idea. There's a (long) discussion here about it: http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/b85dfb2f2006c9f0

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Any reason not to use this in a debugging environment? – Chris Dutrow Aug 25 '12 at 18:25
  • @ChrisDutrow: Depends on your requirements. The problem is that what works in today's browser may not work in tomorrow's. – Tim Down Sep 07 '12 at 14:42
  • 4
    How? If history has proven anything, then it's the opposite: What works today is about the only thing guaranteed to work in tomorrow's browsers as well. Any browser that changes in a backwards incompatible way, breaking existing websites, will be committing suicide market share wise. – Stijn de Witt Jul 24 '13 at 19:39
  • 1
    This is why W3C's attempts to deprecate tags like and has failed. This is also why things like the name attribute on form fields or expressions like 'form.myField.value' still work. This is why IANA's silly attempt to kill of the text/javascript mime type is destined to fail. You cannot deprecate/obsolete/kill that which is actively used all over the web. – Stijn de Witt Jul 24 '13 at 19:41
  • Popular frameworks like Prototype JS are actively using function introspection through the toString() method. This virtually guarantees problems for browsers that don't support it. They will lose market share. ( https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js line 117) – Stijn de Witt Jul 24 '13 at 19:44
  • If the web until now has proven anything it's that it does not like breaking changes and it does not like fragmentation. Things like WAP (for mobiles) or XHTML have spectacularly failed because they represent a breaking or fragmenting change. People don't want to surf some sub-web. They want to serve THE world wide web and nothing else. Mobile browsers need to support Prototype JS, jQuery etc to stand a chance to get market share. No one cares about standards when they are not helping. And EcmaScript is the one they care about least. That's why we all keep calling it Javascript. :) – Stijn de Witt Jul 24 '13 at 19:49
  • @StijndeWitt: I see your point, but I think this is a niche feature only of interest to developers. Browser vendors have historically had no worries about changing the output of `toString()` on functions. Since the standard is permissive and there is no consensus and hence no de facto standard, there isn't much to stop future changes. And with all due respect to Prototype, it's not the player it was and I'm not sure that releasing a new browser version with function stringification that is not parsed correctly by Prototype is going to have any significant effect on the browser's popularity. – Tim Down Jul 24 '13 at 22:11
  • ...minification! and it all goes haywire anyway. – scravy Oct 04 '15 at 10:57
  • 1
    @DanRandolph: In my opinion this was a good answer in 2010 but is now slightly out of date because the `name` property is now standardized in ES2015. However, IE still doesn't support `name` so it's still relevant. – Tim Down Dec 29 '15 at 17:05
10

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;
}

Note: Using Function.caller is non-standard and arguments.callee is forbidden in strict mode.

Vlad A. Ionescu
  • 2,638
  • 1
  • 16
  • 19
5

Here's what I use to put class names in error messages. It includes code to get the name of functions, which works in most browsers.

Obviously, there is no standard way that always works, so you should always provide a name that can be used if no other name is found.

var nameFromToStringRegex = /^function\s?([^\s(]*)/;

/**
 * Gets the classname of an object or function if it can.  Otherwise returns the provided default.
 *
 * Getting the name of a function is not a standard feature, so while this will work in many
 * cases, it should not be relied upon except for informational messages (e.g. logging and Error
 * messages).
 *
 * @private
 */
function className(object, defaultName) {
    var result = "";
    if (typeof object === 'function') {
        result = object.name || object.toString().match(nameFromToStringRegex)[1];
    } else if (typeof object.constructor === 'function') {
        result = className(object.constructor, defaultName);
    }
    return result || defaultName;
}
kybernetikos
  • 8,281
  • 1
  • 46
  • 54
  • It does'n work on Chrome Version 59.0.3071.115 (Official Build) (64-bit) for `/* ReferenceError: object_someMethod is not defined */ var Enforcer = function () { try { object_someMethod; } catch (e) { console.log(e); } }; Enforcer.query = function () { try { object_someMethod; } catch (e) { console.log(e); } }` – samm Nov 24 '17 at 02:54
  • ```/* ReferenceError: object_someMethod is not defined */ var Enforcer = function Enforcer() { try { object_someMethod; } catch (e) { console.log(e); } }; Enforcer.query = function () { try { object_someMethod; } catch (e) { console.log(e); } }``` – kybernetikos Nov 24 '17 at 11:36
2

One interesting way I'm experimenting with is a declaration like the following:

var test1 = function test1(){
    alert(1);
};

It's a little hacky, but what ends up happening is test1 is a local variable that holds a [Function: test1] object.

Here's what happens when you use code based on it:

test1(); //runs the function as expected
console.log(test1.name); //prints 'test1'

So if you do the following:

obj1.func = test1;

You'll then be able to reference obj1.func.name and it'll return 'test1'.

jdotjdot
  • 16,134
  • 13
  • 66
  • 118
2

This is probably the best way to do it:

var myfunc = function () {};
var funcName = myfunc.constructor.name;

This can be done outside the execution of the function, and you can check within the context of the browser console.

Happy coding!

imalvinz
  • 89
  • 4
  • 2
    It does'n work on Chrome Version 59.0.3071.115 (Official Build) (64-bit), printing `funcName` outputs "Function" – samm Nov 24 '17 at 02:54
0

You could convert your function into a string (fn + '') and split it later at whitespace and open bracket /\s|\(/.

var getFunctionName = function (fn) {
   return (fn + '').split(/\s|\(/)[1];
};
yckart
  • 32,460
  • 9
  • 122
  • 129
  • It does'n work on Chrome Version 59.0.3071.115 (Official Build) (64-bit) for `// ReferenceError: object_someMethod is not defined var Enforcer = function () { try { object_someMethod; } catch (e) { console.log(e); } }; Enforcer.query = function () { try { object_someMethod; } catch (e) { console.log(e); } }` – samm Nov 24 '17 at 02:52