获取在Chrome控制台中打印的功能名称

时间:2014-01-09 07:24:14

标签: javascript method-names

考虑此代码:

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

Chrome将 o.f {} 打印到控制台。你知道如何调用 o.f 部分吗?更重要的是,有没有办法在不使用控制台的情况下获得此结果?我想从函数本身中提取方法的名称,也就是说,没有任何其他信息。

我已经知道如何在这种情况下获得名称:

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

但在上述情况下它的行为方式并不相同。


以下内容主要是从comments复制的。

我想知道是否有一个“技术”词来讨论这个o.f模式,比如说“namespace”,“identifier”或“function path”。然后,我想知道是否有办法从网页中加载的脚本中检索此信息。以下问题可以帮助您理解我的目标,即第一个代码块与我的想法非常接近后的段落:Does Chrome retain each object's constructor?

也许我应该提到我的最初目标是在运行时生成文档:/在这种情况下,像反射API这样的东西会有所帮助。更确切地说,我正在寻找一种方法,将方法的名称包含在函数的分解形式中。看:

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

Class.prototype.method + ''给出function(){}。我想注入方法的名称来获得这个结果:function method(){}

问题是我没有任何关于我当前正在序列化的功能的信息,因为当用户点击链接时会发生操作。我知道我可以轻松地将名称存储在某处,例如将数据绑定到锚元素,这对我来说很明显,我只是想知道是否有办法以与Chrome相同的方式检索此数据。

3 个答案:

答案 0 :(得分:2)

嗯,这似乎是一个简单的问题,就所有这些结构的命名而言:

o.f = function(){};

是一个常见语句,由更常见的表达式组成。 o.f只是访问对象属性的两种方法之一,通常称为点符号。虽然我相信JS中的点(。)并不是真正被视为运算符,但我将其称为此后的运算符成员。
接下来我们有着名的赋值运算符,它将右侧操作数分配给左侧(对象o的成员,称为f)。
右手表达式(需要被评估为单数值)是一个函数定义,而不是单独使用一个语句作为表达式。鉴于这一事实,我们将函数的这种用法称为函数表达式

在这种特殊情况下,该函数没有名称,它是一个匿名函数。在内部,大多数 - 如果不是所有引擎 - 都会给它一个名字,但这不是JS应该知道或确实关心的东西。就JS而言,此函数没有名称,只能通过o.f访问。如果你像这样调用这个函数:o.f(),它的上下文将是对象o的上下文,有效地使这个函数表现为一种方法。
所以基本上你的语句如下所示:“分配,并在需要时创建o成员f,这是一个匿名函数。”函数本身没有名字。

考虑一下:

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

所以说o.f函数的名称f并不总是适用。其他变量或属性可以引用相同的函数。那是因为函数是 第一类对象 ,它们可以被返回,传递给任何东西,并由它们分配。

然后,答案是使用以下两种方法中的任何一种:

您可以通过添加名称来更改函数表达式,将其转换为命名函数表达式

f.o = function newName(){};

除了IE的旧版本之外,newName名称在函数范围之外不可用。这是ECMA规范see the details here所要求的。无论如何,现在我们可以检查:

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

该函数的名称仅限于其自己的范围。

使用一个有点hacky的正则表达式,并且不会引用引用相同函数对象的两个变量/属性:

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+'(')
        );
    }
}

这会对函数进行字符串化(给出function (){/*body*/}),并将function (替换为function <propertyName>(。如果函数已经有自己的名称,则不替换该名称。

答案 1 :(得分:1)

一般来说,这在Javascript或一般的编程中并不常见。

但是,function确实有一个属性名称 - 请参阅Function.name。 但是在你的代码中o.f是一个无名的函数。

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

您可以在()

之前定义名称
var o = {};
o.f = function f(){}; //function f(){} creates a function with the name f

然后

o.f.name == 'f'

注意:IE不支持此功能,并且不是EMCA的规范

答案 2 :(得分:0)

这是作为函数的name属性公开的,如今它已成为标准的一部分(在spec中搜索SetFunctionName)。另请参见MDNChrome Platform Statusbrowser support。如果您要从匿名函数的变量名称中自动猜测名称的功能,则MDN会调用推断的函数名称。

当有人问这个问题时,这个话题的最终讨论是kangax的文章Named function expressions demystified(现在已经过时了)。