JavaScript: Get Argument Value and NAME of Passed Variable

62,690

Solution 1

The short answer is that you can't.

The longer, evil answer is that you sort of can with some real nastiness. And it only works when called from another function.

there are two interesting attributes available to you that could help

arguments.callee caller

for fn to do something like this:

(function(){
  var showMe = function(s){
    alert(arguments.callee.caller.toString().match(/showMe\((\S)\)/)[1] + 
    ' = '+ s)
  }
  x = 1
  showMe(x)
})()

What arguments.callee.caller.toString().match(..)[1] does is look for the showMe being called in the function calling it and prints it and its value.

But this is still pretty limited because it will only hit the first call of showMe(x). So if there is two calls to it, it won't work.

But, it was fun to play with these arcane things.

Solution 2

var x = "anything";

function showName(s) {
    alert(s + " = " + eval(s));
}

showName("x");

Not recommended, but there it is.

Solution 3

You could create a hash and pass that in:

var x = {a: 1,b:2}
function showVars(y) {
    for (var z in y) { alert(z + " is " + y[z]); }
}
showVars(x);

This doesn't necessarily show the name of the variable, but it does allow for key-value pairs, which may be more to the point of what you need.

Solution 4

This is what I use for debugging. No global variables, no eval, no arguments.callee or arguments.caller:

var Helpers = (function () {
    // ECMAScript 5 strict mode
    'use strict';

    var Module = {};

    Module.debug = function () {
        var i;

        for (i = 0; i < arguments.length; i++) {
            console.log(arguments[i] + ':', this[arguments[i]]);
        }
    };

    Module.SomeObject = function SomeObject() {
        this.someMember = 1;
        this.anotherMember = 'Whatever';

        Module.debug.call(this, 'someMember', 'anotherMember');

        var privateMember = {
            name: 'Rip Steakface',
            battleCry: 'Raaaaaaaaahhhhhhhhhrrrrrrrrrg!'
        };

        Module.debug.call(privateMember, 'name', 'battleCry');
    };

    return Module;
}());

For those who are wondering why you would want to do this, it's just a way to efficiently log multiple variables along with their names.

If you want to be able to log nested members, as in Module.debug.call(obj, 'hair.fluffiness'), you can modify the function like so:

Module.debug = function () {
    var i, j, props, tmp;

    for (i = 0; i < arguments.length; i++) {
        tmp = this;
        props = arguments[i].split('.');

        for (j = 0; j < props.length; j++) {
            tmp = tmp[props[j]];
        }

        console.log(arguments[i] + ':', tmp);
    }
};

Unfortunately, I can't find any way to efficiently log multiple private variables that aren't members of an object, e.g. var roll = 3, value = 4; Module.debug.call(???);

Solution 5

Not sure you can directly get what you want from JavaScript, since the variable name is not carried around with the value it references (think of variable names as identifiers only the compiler knows about; but which get thrown away at runtime).

You can, however, do something slightly different which allows for passing around named arguments. Create an anonymous object and pass that to your function:

function showNames(o)
{
    for( var ix in o )
    {
       alert( ix + ":" + o[ix] );
    }
}

var z = { x : "Anything" }
showNames( z );
// or
showNames( { a : "ay", b : "bee", c: "see" } )

For iterating object properties, I tend to prefer a functional-style, as in:

Array.iteri = function(o, f)
{
    for(var i in o) { f(i, o[i]) }
}

function showNames(o)
{
    Array.iteri( o, function(i,v)
    {
        alert( i + ": " + v )
    });
}
showNames( { a : "ay", b : "bee", c: "see" } )
Share:
62,690
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    What I want to do is get the NAME of a variable passed to a function and the VALUE of that variable, and only have to pass in one variable to the function. So:

    var x = "anything";
    
    function showName() {
    
    }
    
    showName(x);
    

    or

    showName("x");
    

    Which will return: "x = anything".

    Right now, I have to specify the variable twice:

    showName("x", x);
    

    In order to get the name and value of the variable I am passing in.

    Note that I am not interested in the name of argument in the prototype of showName, but the name of the variable in the calling function. Also, the variable passed may be local, so I can't use the window object to find the variable.

  • BaroqueBobcat
    BaroqueBobcat about 15 years
    What about x=1; showName(x) ?
  • D'Arcy Rittich
    D'Arcy Rittich about 15 years
    @BaroqueBobcat - the above function works fine for me. If you are looking for edge cases, the function can easily be modified to stringify the data in different ways based on type or value. E.g., an empty array and empty string both display as empty. You may want to handle this differently, or add additional info about a best guess as to type. The point of the example is not to be bulletproof but to demonstrate that a function can obtain both parameter name and value from one scalar parameter.
  • Daniel Mendel
    Daniel Mendel over 12 years
    +1, disgusting and fascinating.
  • James Hugard
    James Hugard over 11 years
    @ally - I was speaking conceptually, but most javascript engines do (or can) compile to intermediate code for performance. AFAIK, only Chrome compiles javascript directly to assembly language.
  • Admin
    Admin almost 10 years
    This will error on Firefox and Safari when caller is null
  • BaroqueBobcat
    BaroqueBobcat almost 10 years
    @Jhawins true. There's probably a hacky way around that if you can get a reference to the string of the source somehow.
  • pcarvalho
    pcarvalho almost 6 years
    this will never print x = {a: 1,b:2}, so its not what the OP "needs"
  • pcarvalho
    pcarvalho almost 6 years
    deprecated since ECMAScript (ES5) :(