Determine original name of variable after its passed to a function
Asked Answered
B

9

37

I've got a feeling this might not be possible, but I would like to determine the original variable name of a variable which has been passed to a function in javascript. I don't know how to explain it any better than that, so see if this example makes sense.

function getVariableName(unknownVariable){
  return unknownVariable.originalName;
}

getVariableName(foo); //returns string "foo";
getVariableName(bar); //returns string "bar";

This is for a jquery plugin i'm working on, and i would like to be able to display the name of the variable which is passed to a "debug" function.

Brannen answered 4/8, 2010 at 9:6 Comment(5)
I am not sure what is the purpose of this, since you would need to get interested in variable values than the variable name.Alfred
There are no variable names when a program is running. No "current" ones, and no "original" ones.Cavallaro
Haha, I figured this was a longshot, but worth a shot nonetheless. There isn't too much purpose, but if you want context you can see the current version of the plugin: andygroff.com/jquery-debugger-debugging-plugin If you view the object example, I would prefer that the title says "clothingCompany Properties" instead of simply "Object Properties" Its not terribly important, but would be nice.Brannen
Somewhat related feature request: Suggestion to add nameof() to TypeScript compiler. If this ever lands you could do nameof(foo) // returns the string "foo".Aneurysm
I've updated my answer below which gets you really close using ES6. Just add curly brackets.Aneurysm
T
24

You're right, this is very much impossible in any sane way, since only the value gets passed into the function.

Tisdale answered 4/8, 2010 at 9:8 Comment(6)
what's the insane way?Butterandeggs
Get a backtrace, get the file and line number of the function invocation, load the source code of that file, find and parse that line, try to figure out which variable was your parameter. Since there may be any number of function calls on one line and functions may be aliased at runtime, not to mention the complexity of the task, I hope the insanity of this is self evident.Tisdale
This is now somewhat possible, see my answer.Heartbreaker
This is provably possible in conditions where all variables have a unique value. See my answer for the code.Coldhearted
@Perry You can certainly construct very specific situations in which you can reverse a value to a variable name, but it is far from generalizable.Tisdale
@Tisdale Worked thru the answers again and I now feel that offirmo's is the best one. I've left mine up as a reference since it may be helpful in certain select use cases, though I agree it's not generalizable.Cran
H
12

This is now somehow possible thanks to ES6:

function getVariableName(unknownVariableInAHash){
  return Object.keys(unknownVariableInAHash)[0]
}

const foo = 42
const bar = 'baz'
console.log(getVariableName({foo})) //returns string "foo"
console.log(getVariableName({bar})) //returns string "bar"

The only (small) catch is that you have to wrap your unknown variable between {}, which is no big deal.

Heartbreaker answered 15/9, 2017 at 1:28 Comment(4)
{foo} is just {foo:42}... so you're just sending it as an object. See New notations in ECMAScript 2015: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Whitelivered
@CodyG. I'm perfectly aware of that.Heartbreaker
Then you shouldn't say "somehow possible thanks to es6", your answer is basically --- 'you can do this by sending the value as an object with the key as the variable name'... which is also easily done in es5 with a polyfill of Object.keys, or simply by passing an object with the variable name as another property.Whitelivered
I really liked this idea, but the (big) catch is you can no longer treat your unknown variable like a normal variable, so you're going to have to rewrite your functions to work with objects. For example, if you had this line in your function unknownVariableInAHash + 1 it will no longer work as it did before "wrapping your unknown variable between {}", so it seems like it is a big deal.Neurosurgery
T
4

As you want debugging (show name of var and value of var), I've been looking for it too, and just want to share my finding.

It is not by retrieving the name of the var from the var but the other way around : retrieve the value of the var from the name (as string) of the var.

It is possible to do it without eval, and with very simple code, at the condition you pass your var into the function with quotes around it, and you declare the variable globally :

foo = 'bar';

debug('foo'); 

function debug(Variable) { 
 var Value = this[Variable]; // in that occurrence, it is equivalent to
 // this['foo'] which is the syntax to call the global variable foo
 console.log(Variable + " is " + Value);  // print "foo is bar"
}
Tupungato answered 31/12, 2018 at 17:1 Comment(0)
A
1

Global w/string method

Here is a technique that you can use to keep the name and the value of the variable.

// Set up a global variable called g
var g = {};
// All other variables should be defined as properties of this global object
g.foo = 'hello';
g.bar = 'world';

// Setup function
function doStuff(str) {
  if (str in g) {
    var name = str;
    var value = g[str];
    // Do stuff with the variable name and the variable value here
    // For this example, simply print to console
    console.log(name, value);
  } else {
    console.error('Oh snap! That variable does not exist!');
  }
}

// Call the function
doStuff('foo'); // log: foo hello
doStuff('bar'); // log: bar world
doStuff('fakeVariable'); // error: Oh snap! That variable does not exist!

This is effectively creating a dictionary that maps variable names to their value. This probably won't work for your existing code without refactoring every variable. But using this style, you can achieve a solution for this type of problem.

ES6 object method

In ES6/ES2015, you are able to initialize an object with name and value which can almost achieve what you are trying to do.

function getVariableName(unknownVariable) {
  return Object.keys(unknownVariable)[0];
}

var foo = 'hello';
var output = getVariableName({ foo }); // Note the curly brackets
console.log(output);

This works because you created a new object with key foo and value the same as the variable foo, in this case hello. Then our helper method gets the first key as a string.

Credit goes to this tweet.

Aneurysm answered 12/10, 2013 at 1:12 Comment(2)
Thanks for the answer. This is a nice solution, although it really doesn't solve the problem I had. I was writing a debugging plugin which was going to create a modal alert with information on variables, including its name. It would need to run with any javascript, so storing all variables as object properties isn't a viable solution. Thanks!Brannen
@AndyGroff substituting the g variable for the window variable might solve your problem. But ultimately you will have to access the variables by string instead of the identifier.Aneurysm
C
1

Well, all the global variables are properties of global object (this or window), aren't they? So when I wanted to find out the name of my variables, I made following function:

var getName = function(variable) {
  for (var prop in window) {
    if (variable === window[prop]) {
      return prop;
    }
  }
}
var helloWorld = "Hello World!";
console.log(getName(helloWorld)); // "helloWorld"

Sometimes doesn't work, for example, if 2 strings are created without new operator and have the same value.

Coreencorel answered 7/6, 2014 at 19:37 Comment(2)
Does this depend on being run in the browser? Or am I misunderstanding what window is?Soddy
This won't work if two objects have the same value. window.a=1;window.b=1; It will return the name of the first matching value. Additionally, it is bad practice to define variables in the global scope.Aneurysm
C
0

Use a 2D reference array with .filter()

Note: I now feel that @Offermo's answer above is the best one to use. Leaving up my answer for reference, though I mostly wouldn't recommend using it.

Here is what I came up with independently, which requires explicit declaration of variable names and only works with unique values. (But will work if those two conditions are met.)

// Initialize some variables
let var1 = "stick"
let var2 = "goo"
let var3 = "hello"
let var4 = "asdf"


// Create a 2D array of variable names
const varNames = [
    [var1, "var1"],
    [var2, "var2"],
    [var3, "var3"]
]


// Return either name of variable or `undefined` if no match
const getName = v => varNames.filter(name => name[0] === v).length
  ? varNames.filter(name => name[0] === v)[0][1]
  : undefined


// Use `getName` with OP's original function
function getVariableName(unknownVariable){
  return getName(unknownVariable)
}

Cran answered 4/4, 2021 at 4:33 Comment(0)
B
0

This is my take for logging the name of an input and its value at the same time:

function logVariableAndName(unknownVariable) {
  const variableName = Object.keys(unknownVariable)[0];
  const value = unknownVariable[variableName];
  console.log(variableName);
  console.log(value);
}

Then you can use it like logVariableAndName({ someVariable })

Blesbok answered 25/11, 2022 at 19:0 Comment(0)
G
-1

Converting a set of unique variable into one JSON object for which I wrote this function

function makeJSON(){ //Pass the variable names as string parameters [not by reference]
ret={};
for(i=0; i<arguments.length; i++){
    eval("ret."+arguments[i]+"="+arguments[i]);
}
return ret;
}

Example:

a=b=c=3;
console.log(makeJSON('a','b','c'));

Perhaps this is the reason for this query

Guglielma answered 17/12, 2015 at 2:52 Comment(1)
ret[x] = x; absolutely no reason for eval here!Tisdale
C
-2

I think you can use

getVariableName({foo});
Chrysotile answered 9/7, 2020 at 15:23 Comment(1)
Multiple existing answers already recommended that.Reo

© 2022 - 2024 — McMap. All rights reserved.