3

Considering this code :

var o = {};
o.f = function(){};
new o.f;

Chrome prints o.f {} into the console. Do you know how this o.f part is called? More importantly, is there any way to get this result without using the console? I'd like to extract the name of a method from the function itself, that is to say, without any additional information.

I already know how to get the name in this case :

function f(){}
f+'' // "function f(){}"

But it does not behave the same way in the situation described above.


The following content is mostly copied from comments.

I wanted to know if there is a "technical" word to talk about this o.f pattern, let's say for example "namespace", "identifier", or "function path". Then, I was wondering if there was a way to retrieve this information from a loaded script in a webpage. The following question may help you in understanding my goal, the paragraph which is right after the first code block is quite close to my idea : Does Chrome retain each object's constructor?.

Maybe I should have mentioned that my original goal was to generate a documentation at runtime :/ Something like a reflection API would have been helpful in this case. More precisely, I was looking for a way to include the name of a method into the decompilated form of the function. Look :

function Class(){}
Class.prototype.method = function(){};

Class.prototype.method + '' gives function(){}. I'd like to inject the method's name to get this result : function method(){}.

The problem is that I don't have any information about which function I'm currently serializing since the operation occurs when the user clicks a link. I know I could easily store the name somewhere, binding the data to the anchor element for example, that's obvious to me, I was just curious to know if there was a way to retrieve this data the same way as Chrome.

Community
  • 1
  • 1
  • What do you need it for? – zerkms Jan 09 '14 at 07:26
  • There's no way with js (as far as I know) – Edgar Villegas Alvarado Jan 09 '14 at 07:26
  • possible duplicate of [Can I get the name of the currently running function in JavaScript?](http://stackoverflow.com/questions/1013239/can-i-get-the-name-of-the-currently-running-function-in-javascript) – Quentin Jan 09 '14 at 07:28
  • 2
    @Quentin no, that's another question. wared basically wants to know how to get the 'parent' object – Edgar Villegas Alvarado Jan 09 '14 at 07:29
  • I think you want to get the constructor name, don't you? `new o.f` creates a new instance of `o.f`. – Tobias Jan 09 '14 at 07:32
  • @Quentin There is no connection between these two questions. I've added some details. –  Jan 09 '14 at 07:32
  • @still_learning No, I want the name of the method. –  Jan 09 '14 at 07:34
  • @zerkms Spare time coding. –  Jan 09 '14 at 07:36
  • @wared — `f` *is* the "name" of the method. (It's actually the name of the property to which the method is assigned, the method itself doesn't have a name since you didn't specify one in your function expression). Are you asking for the name of the variable storing the object that owns to the property to which the method is assigned? – Quentin Jan 09 '14 at 07:36
  • @wared: my question was more about why it matters for you. Why do you need to know the exact name? – zerkms Jan 09 '14 at 07:37
  • @zerkms To print it on the screen. –  Jan 09 '14 at 07:38
  • In other words, "What problem will finding the name solve for you? There might be a better way to solve *that* problem". See also: http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Quentin Jan 09 '14 at 07:38
  • @wared: for what? It's just a reference name, you should never rely on it – zerkms Jan 09 '14 at 07:39
  • @zerkms I'm just curious, I'm sorry but I've no more details to provide. –  Jan 09 '14 at 07:53
  • @wared "Do you know how this o.f part is called?" What do you mean by "called"? Are you asking how that is printed to the screen? – Whymarrh Jan 31 '14 at 02:29
  • This link may be of interest: [State of function decompilation in Javascript](http://perfectionkills.com/state-of-function-decompilation-in-javascript/). – Whymarrh Jan 31 '14 at 02:33
  • @Whymarrh I wanted to know if there is a "technical" word to talk about this `o.f` pattern, let's say for example "namespace", "identifier", or "function path". Then, concerning your last question, not really. I was wondering if there was a way to retrieve this information from a loaded script in a webpage. The following question may help you in understanding my goal, the paragraph which is right after the first code block is quite close to my idea : http://stackoverflow.com/q/21382811/1636522 - I bet you come from there :) (Very interesting article, thanks.) –  Jan 31 '14 at 06:50
  • @Whymarrh Maybe I should have mentioned that my original goal was to generate a documentation at runtime :/ Something like a reflection API would have been helpful in this case. More precisely, I was looking for a way to include the name of a method into the decompilated form of the function. –  Jan 31 '14 at 07:07
  • @Whymarrh I've updated the question, see the `Class.prototype.method + ''` part. –  Jan 31 '14 at 07:33
  • @wared: Edited my answer, giving you more details, an actual answer to your question, and 2 possible solutions for doing what it is you're actually trying to do – Elias Van Ootegem Feb 07 '14 at 07:51

3 Answers3

2

Well, this seems a simple enough question, as far as the naming of all these constructs goes:

o.f = function(){};

is a common statement, consisting of even more common expressions. o.f is simply one of 2 ways to access an objects' properties, commonly referred to as the dot-notation. Though I believe in JS the dot (.) isn't really seen as an operator, I'll be referring to it as the member-of operator henceforth.
Next we have the well-known assignment-operator, which assigns the right-hand operand to the left (member of the object o, called f).
The right-hand expression (needs to be evaluated to a singular value) is a function definition that, instead of a statement on its own, is used as an expression. Given that fact, we refer to this usage of functions as function expressions.

In this particular case, the function has no name, it's an anonymous function. Internally, most -if not all engines- will give it a name, but that's not something JS should know or indeed care about. As far as JS is concerned, this function has no name, and is only accessible through o.f. If you call this function like so: o.f(), its context will be that of the object o, effectively making this function behave as a method.
So basically your statement reads like this: "Assign, and create if required, to the member of o called f, an anonymous function." The function itself has no name.

Consider this:

var o = {f: function(){console.log('I am a function');}};
var foobar = o.f;
foobar();//logs I am a function

So saying the name of the function o.f is f doesn't always apply. Other variables or properties can reference the same function. That's because functions are first class objects, they can be returned, passed to and assigned to, from and by anything.

The answer, then, is to use either one of these 2 approaches:

You can change the function expression by adding a name, to turn it into a named function expression:

f.o = function newName(){};

The newName name is, apart from older versions of IE, not available outside of the functions' scope. This is required by the ECMA specifications see the details here. Anyway, now we can check for that:

var func = function func(){console.log(func);};
//same name:
func();//logs function func(){}
var foobar = func;
foobar();//logs function func(){}
func = 123;//<-- no longer function
foobar();//still function func(){}//func is still accessible
var hidden = (function()
{
    return function named()
    {
        console.log(named);//access name
    };
}());
hidden();//logs function named(){}
console.log(named);//undefined -> not visible outside the function itself

The name of the function is restricted to its own scope.

Use a regex, which is slightly hacky, and doesn't pick up on two variables/properties referencing the same function object:

o = {f: function(){console.log('I am a function');}};
for (var pName in o)
{//probably add o.hasOwnProperty(pName) check to be safe
    if (o[pName] instanceof Function)
    {
        console.log(o.f.toString().replace(
            /^function\s*\(/,
            'function o.'+pName+'(')
        );
    }
}

This stringifies the function (giving function (){/*body*/}) and replaces function ( with function <propertyName>(. If the function already had a name of its own, that name is not replaced.

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • So there is no Chrome secret place :) Anyway, all this is pretty interesting. Thanks! –  Feb 07 '14 at 10:01
1

In general, this is not common practice in Javascript or in programming in general.

However, functions do have an attribute name - see Function.name. but in your code o.f is a nameless function.

var o = {};
o.f = function(){}; //function (){} creates a nameless function.

you can define a name before the ()

var o = {};
o.f = function f(){}; //function f(){} creates a function with the name f

then

o.f.name == 'f'

NOTE: this functionality is NOT supported in IE, and is not a specification of EMCA

TastySpaceApple
  • 3,115
  • 1
  • 18
  • 27
0

This is exposed as the name property of the function, and these day it is part of the standard (search for SetFunctionName in the spec). See also MDN, Chrome Platform Status, browser support. If you are asking specifically about the feature of auto-guessing the name from the variable name for anonymous functions, MDN calls that the inferred function name.

Back when the question was asked, the definitive discussion of this topic was kangax's article Named function expressions demystified (now a bit outdated).

Tgr
  • 27,442
  • 12
  • 81
  • 118