考虑此代码:
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相同的方式检索此数据。
答案 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
)。另请参见MDN,Chrome Platform Status,browser support。如果您要从匿名函数的变量名称中自动猜测名称的功能,则MDN会调用推断的函数名称。
当有人问这个问题时,这个话题的最终讨论是kangax的文章Named function expressions demystified(现在已经过时了)。