1

是否可以找到匿名函数的名称?

例如试图找到一种方法来提醒anonyFufindMe在此代码http://jsfiddle.net/L5F5N/1/

function namedFu(){
    alert(arguments.callee);
    alert(arguments.callee.name);
    alert(arguments.callee.caller);
    alert(arguments.caller);
    alert(arguments.name);
}

var anonyFu = function() {
    alert(arguments.callee);
    alert(arguments.callee.name);
    alert(arguments.callee.caller);
    alert(arguments.caller);
    alert(arguments.name);
}

var findMe= function(){ 
    namedFu();
    anonyFu();
}
findMe();

这是为了一些内部测试,所以它不需要跨浏览器。事实上,即使我必须安装插件,我也会很高兴。

4

5 回答 5

1

怀疑这可能是你得到它的方式。对于初学者,如果您添加了一行

var referenceFu = anonyFu;

您希望其中哪些名称能够登录?两者都只是参考。

然而——假设你有能力改变代码——这是有效的 javascript:

var anonyFu = function notActuallyAnonymous() {
    console.log(arguments.callee.name);
}

这将记录"notActuallyAnonymous". 因此,您可以只为您有兴趣检查的所有匿名函数添加名称,而不会破坏您的代码。

不确定这是否有帮助,但这就是我所得到的。

于 2012-11-06T22:43:25.050 回答
1

您可以通过使用 arguments.callee 以编程方式从函数内部识别函数的任何属性,甚至是未命名的匿名函数。所以你可以用这个简单的技巧来识别函数:

每当您创建一个函数时,请为其分配一些属性,以便以后识别它。

例如,总是创建一个名为 id 的属性:

var fubar = function() {
   this.id = "fubar";
   //the stuff the function normally does, here
   console.log(arguments.callee.id);
}

arguments.callee 本身就是函数,因此该函数的任何属性都可以像上面的 id 一样访问,甚至是您自己分配的属性。

Callee 已被官方弃用,但仍然适用于几乎所有浏览器,并且在某些情况下仍然没有替代品。您只是不能在“严格模式”下使用它。

当然,您也可以命名匿名函数,例如:

var fubar = function foobar() {
   //the stuff the function normally does, here
   console.log(arguments.callee.name);
}

但这显然不那么优雅,因为(在这种情况下)你不能在两个地方都将它命名为 fubar。我必须将实际名称设为 foobar。

如果您的所有函数都有描述它们的注释,您甚至可以抓住它,如下所示:

var fubar = function() {
   /* 
      fubar is effed up beyond all recognition 
      this returns some value or other that is described here
    */
   //the stuff the function normally does, here
   console.log(arguments.callee.toString().substr(0, 128);
}

请注意,您还可以使用 argument.callee.caller 来访问调用当前函数的函数。这使您可以从外部访问函数的名称(或属性,如 id 或文本中的注释)。

你这样做的原因是你想找出什么叫做有问题的函数。首先,这可能是您希望以编程方式查找此信息的原因。

因此,如果上面的 fubar() 示例之一调用了以下函数:

var kludge = function() {
   console.log(arguments.callee.caller.id); // return "fubar" with the first version above
   console.log(arguments.callee.caller.name); // return "foobar" in the second version above
   console.log(arguments.callee.caller.toString().substr(0, 128);
     /* that last one would return the first 128 characters in the third example, 
        which would happen to include the name in the comment. 
        Obviously, this is to be used only in a desperate case, 
        as it doesn't give you a concise value you can count on using)
     */
}
于 2014-01-23T19:40:40.537 回答
1

我将补充一点,如果您知道该函数在哪个对象中,那么您可以将代码添加到该对象或通常添加到对象原型中,这将获得基于值的键名。

Object.prototype.getKeyByValue = function( value ) {
    for( var prop in this ) {
        if( this.hasOwnProperty( prop ) ) {
             if( this[ prop ] === value )
                 return prop;
        }
    }
}

然后你可以使用

THAT.getKeyByValue(arguments.callee.caller);

曾经使用这种方法进行调试,其中大部分功能都在一个对象中的项目中涉及性能测试。不想以任何其他方式命名所有函数或代码中的双重名称,需要计算每个函数运行的时间 - 这加上函数开始时堆栈上的推送时间和结束时弹出的时间也是如此。

为什么?为每个函数添加非常少的代码,并为每个函数添加相同的代码,以便在控制台上进行测量和调用列表。这是临时的。

THAT._TT = [];
THAT._TS = function () {
  THAT._TT.push(performance.now());
}
THAT._TE = function () {
  var tt = performance.now() - THAT._TT.pop();
  var txt = THAT.getKeyByValue(arguments.callee.caller);
  console.log('['+tt+'] -> '+txt);
};


THAT.some_function = function (x,y,z) {
    THAT._TS();
    // ... normal function job
    THAT._TE();
}

THAT.some_other_function = function (a,b,c) {
    THAT._TS();
    // ... normal function job
    THAT._TE();
}

不是很有用,但也许它会帮助在类似情况下遇到类似问题的人。

于 2014-08-11T11:25:39.610 回答
0

arguments.callee正如MDN所述,它已被弃用:

你应该避免使用arguments.callee()并且只给每个函数(表达式)一个名字。

换句话说:

[1,2,3].forEach(function foo() {
  // you can call `foo` here for recursion
})

如果你想要一个匿名函数的名字分配给一个变量,假设你正在调试你的代码并且你想跟踪这个函数的名字,那么你可以命名它两次,这是一个常见的模式:

var foo = function foo() { ... }

除了 MDN 文档中指定的评估案例之外,我想不出您想要使用的任何其他案例arguments.callee

于 2012-11-06T22:45:29.627 回答
0

没有。根据定义,匿名函数没有name. 但是,如果您想询问函数表达式:是的,您可以将它们命名为

不,在运行时无法获取变量(引用函数)的名称。

于 2012-11-07T00:26:08.873 回答