Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get variable name. javascript "reflection"

Is there a way to get the variable name, like you can do in .Net with reflection?
like in this scenario:

function(x,y,z)
{
    if (x === 0)
        logger.log('variable ' + x.reflectedName ' has invalid value ' + x)
        // logs: 'variable x has invalid value 0)
    ...
}

I found similar questions that wanted the name of the var outside of the function(?!) but couldn't find this question.

(jQuery is an option, though I can't think how it can be done with it...)

like image 954
gdoron is supporting Monica Avatar asked Mar 20 '12 22:03

gdoron is supporting Monica


2 Answers

Actually you CAN. Here is a snippet:

function getVarName(v) {
    for (var key in window) {
        if (window[key] === v)
            return key;
    }
}
var testvar = 13142;
function test(t) {
    var varName = getVarName(t);
    // window[varName] -- your variable actualy
    alert(varName);
}
test(testvar); // testvar

The other problem is if you create some vars that contain the same variable. Then first var will be returned.

like image 141
ovnia Avatar answered Sep 24 '22 15:09

ovnia


Since you're using .NET as an example, let's delve briefly into that. In C#, you could create a function that takes an Expression:

void BadArgument<T>(Expression<Func<T>> argExpr)
{
}

But in order to be able to extract the variable name from a call to this function, you would have to make sure the call always uses exactly the right syntax (even though there is no way to enforce this at compile time):

if(x < 0)
    BadArgument(() => x);

So it can be done, but it's very fragile and pretty slow. You're basically generating instructions to create a whole expression tree based on the lambda expression () => x, just so the function you call can parse out that expression tree and try to find the name of the argument.

Can this sort of thing be done in javascript? Sure!

In javascript, closures are produced via internal functions, so the equivalent of the above lambda expression would be:

function(){return x;}

And since javascript is a scripting language, each function is the equivalent of its own definition as a string. In other words, calling .toString() on the above function will yield:

function(){return x;}

This jsfiddle shows how you can leverage this in a logging-style function. You are then free to parse the resulting function string, which will be only slightly more trouble than parsing the .NET Expression Tree would be. Furthermore, getting the actual value of x is even easier than in .NET: you just call the function!

But just because you can do it doesn't mean you should. It's nice as a gee-whiz parlor trick, but when it comes right down to it, it's not worth it:

  • It's fragile: what if some developer doesn't use it right and gives you a function that you can't parse?
  • It doesn't work with minification: imagine getting a message that variable a had an incorrect value because your minified function changed your variable names.
  • It adds overhead: even a minifier can't shorten function(){return x;} to be smaller than "x".
  • Finally, it's complicated. 'nuff said.
like image 27
StriplingWarrior Avatar answered Sep 22 '22 15:09

StriplingWarrior