Get a function name like printed in Chrome console

自古美人都是妖i 提交于 2019-12-12 13:59:58

问题


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.


回答1:


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.




回答2:


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




回答3:


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).



来源:https://stackoverflow.com/questions/21014020/get-a-function-name-like-printed-in-chrome-console

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!