通过匿名函数获取变量的名称

时间:2012-11-06 22:31:42

标签: javascript function anonymous-function

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

e.g。试图找到一种方法来提醒此代码中的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();

这是针对某些内部测试的,因此不需要跨浏览器。事实上,即使我必须安装插件,我也会很开心。

5 个答案:

答案 0 :(得分:1)

怀疑它是否有可能以你的方式获得它。对于初学者,如果添加了一行

var referenceFu = anonyFu;

您希望能够记录哪些名称?他们都只是参考。

但是 - 假设您有能力更改代码 - 这是有效的javascript:

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

会记录"notActuallyAnonymous"。因此,您可以在不破坏代码的情况下,为您有兴趣检查的所有匿名函数添加名称。

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

答案 1 :(得分: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)
     */
}

答案 2 :(得分: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();
}

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

答案 3 :(得分: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的任何其他案例。

答案 4 :(得分:0)

没有。根据定义,匿名函数没有name。但是,如果你想要求函数表达式:是的,你可以name them

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