简体   繁体   中英

getting the name of a variable through an anonymous function

Is it possible to find the name of an anonymous function?

eg trying to find a way to alert either anonyFu or findMe in this code 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();

This is for some internal testing, so it doesn't need to be cross-browser. In fact, I'd be happy even if I had to install a plugin.

Doubt it's possible the way you've got it. For starters, if you added a line

var referenceFu = anonyFu;

which of those names would you expect to be able to log? They're both just references.

However – assuming you have the ability to change the code – this is valid javascript:

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

which would log "notActuallyAnonymous" . So you could just add names to all the anonymous functions you're interested in checking, without breaking your code.

Not sure that's helpful, but it's all I got.

You can identify any property of a function from inside it, programmatically, even an unnamed anonymous function, by using arguments.callee. So you can identify the function with this simple trick:

Whenever you're making a function, assign it some property that you can use to identify it later.

For example, always make a property called id:

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

arguments.callee is the function, itself, so any property of that function can be accessed like id above, even one you assign yourself.

Callee is officially deprecated, but still works in almost all browsers, and there are certain circumstances in which there is still no substitute. You just can't use it in "strict mode".

You can alternatively, of course, name the anonymous function, like:

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

But that's less elegant, obviously, since you can't (in this case) name it fubar in both spots; I had to make the actual name foobar.

If all of your functions have comments describing them, you can even grab that, like this:

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);
}

Note that you can also use argument.callee.caller to access the function that called the current function. This lets you access the name (or properties, like id or the comment in the text) of the function from outside of it.

The reason you would do this is that you want to find out what called the function in question. This is a likely reason for you to be wanting to find this info programmatically, in the first place.

So if one of the fubar() examples above called this following function:

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)
     */
}

I will add that if you know in which object that function is then you can add code - to that object or generally to objects prototype - that will get a key name basing on value.

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

And then you can use

THAT.getKeyByValue(arguments.callee.caller);

Used this approach once for debugging with performance testing involved in project where most of functions are in one object. Didn't want to name all functions nor double names in code by any other mean, needed to calculate time of each function running - so did this plus pushing times on stack on function start and popping on end.

Why? To add very little code to each function and same for each of them to make measurements and calls list on console. It's temporary ofc.

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

Not very useful but maybe it will help someone with similar problem in similar circumstances.

arguments.callee it's deprecated, as MDN states:

You should avoid using arguments.callee() and just give every function (expression) a name.

In other words:

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

If what you want is to have a name for an anonymous function assigned to a variable, let's say you're debugging your code and you want to track the name of this function, then you can just name it twice, this is a common pattern:

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

Except the evaling case specified in the MDN docs, I can't think of any other case where you'd want to use arguments.callee .

No. By definition, an anonymous function has no name . Yet, if you wanted to ask for function expressions: Yes, you can name them .

And no, it is not possible to get the name of a variable (which references the function) during runtime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM