417

In PHP you can do amazing/horrendous things like this:

$a = 1;
$b = 2;
$c = 3;
$name = 'a';
echo $$name;
// prints 1

Is there any way of doing something like this with Javascript?

E.g. if I have a var name = 'the name of the variable'; can I get a reference to the variable with name name?

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Finbarr
  • 31,350
  • 13
  • 63
  • 94
  • 2
    Does this answer your question? ["Variable" variables in Javascript?](https://stackoverflow.com/questions/5187530/variable-variables-in-javascript). The accepted answer there is better than the one here because it shows how to do it, but also _correctly warns that there's almost always a better way to do whatever it is you want to do_. See [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) on meta. – ggorlen Dec 06 '19 at 20:37
  • Does this answer your question? [When is it appropriate to use a semicolon?](https://stackoverflow.com/questions/38823062/when-is-it-appropriate-to-use-a-semicolon) – pilchard Feb 18 '23 at 22:50

18 Answers18

406

Since ECMA-/Javascript is all about Objects and Contexts (which, are also somekind of Object), every variable is stored in a such called Variable- (or in case of a Function, Activation Object).

So if you create variables like this:

var a = 1,
    b = 2,
    c = 3;

In the Global scope (= NO function context), you implicitly write those variables into the Global object (= window in a browser).

Those can get accessed by using the "dot" or "bracket" notation:

var name = window.a;

or

var name = window['a'];

This only works for the global object in this particular instance, because the Variable Object of the Global Object is the window object itself. Within the Context of a function, you don't have direct access to the Activation Object. For instance:

function foobar() {
  this.a = 1;
  this.b = 2;

  var name = window['a']; // === undefined
  console.log(name);
  name = this['a']; // === 1
  console.log(name);
}

new foobar();

new creates a new instance of a self-defined object (context). Without new the scope of the function would be also global (=window). This example would alert undefined and 1 respectively. If we would replace this.a = 1; this.b = 2 with:

var a = 1,
    b = 2;

Both alert outputs would be undefined. In that scenario, the variables a and b would get stored in the Activation Object from foobar, which we cannot access (of course we could access those directly by calling a and b).

uingtea
  • 6,002
  • 2
  • 26
  • 40
jAndy
  • 231,737
  • 57
  • 305
  • 359
  • 1
    Another cool thing is that in this way you can add callback (start/end) for any global level function. – antitoxic Aug 07 '12 at 07:39
  • 8
    But what if my dynamic variable is local in a function? for example: function boink() { var a = 1; // this will not work var dynamic = this['a']; // this also wont work var dynamic = ['a']; } – Kokodoko Oct 28 '13 at 11:03
  • @Kokodoko—because *this* isn't "context" or a reference to a function's execution context (there is no way to reference an execution context, it's forbidden by the ECMA-262). *this* is set by how a function is called (or by *bind*), it's just an Object that has nothing to do with the execution context in which it's accessible. – RobG May 13 '15 at 02:55
  • If you need to access nested properties check out http://stackoverflow.com/questions/4244896/dynamically-access-object-property-using-variable/30974910#30974910 – Mr Br Jun 22 '15 at 08:12
  • 1
    pointed me in the right direction with the bracket notation. Was stuck thinking dot notation only. – Andrew Mar 02 '17 at 20:29
  • okay cool! I have a question please, people say don t pollute the global scope, but in the same time this thread demonstrates that the global scope, at the end of the day, is just occuped by all the declared variables? I m a little confused, any hint would be great about this subject – Webwoman Apr 26 '19 at 03:02
169

eval is one option.

var a = 1;
var name = 'a';

document.write(eval(name)); // 1

Warning: Note that using the eval() function is not recommended if you don't know what you are doing, since it brings multiple security issues. Use something else unless absolutely necessary. See the MDN page for eval for more info.

uingtea
  • 6,002
  • 2
  • 26
  • 40
erickb
  • 6,193
  • 4
  • 24
  • 19
  • 29
    No it shouldn't as eval is evil. Never use eval! – EasyBB Jan 18 '14 at 21:18
  • 75
    @EasyBB - if you're going to say never to use something, I't helpful to explain why. I have a situation in which I can't think of any other way to accomplish what I'm doing other than eval() – Rampant Creative Group Mar 25 '14 at 10:54
  • 5
    Eval poses a risk for attacks on end users and we'll it's not technically evil rather misunderstood and misused in a lost of cases. I've seen php responses which hold literal vars in it then use eval to run it. Though this shouldn't be used in this case as there are better methods. This question at hand eval should not be used at all as there are better methods overall and I'm sure a lot of us know this. – EasyBB Mar 25 '14 at 13:26
  • 3
    Via https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/ --- "Let’s consider the arguments most frequently leveled against using eval: 1) It requires a compile and is therefore slow 2) What if a malicious script found its way into the eval argument? 3) It looks ugly 4) It inherits the execution context and this binding of the scope in which its invoked" – mattLummus May 13 '15 at 15:07
  • 1
    Here is how to create dynamic variables using eval: http://stackoverflow.com/a/13291766/5528600 – am2124429 Mar 21 '16 at 12:54
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval – CodeFinity Apr 09 '20 at 11:09
  • 1
    Nothing at frontend can be secure, you can always swap JS to your own anytime, so eval is not that eval because you can always use read-only strings or freeze objects. – Zydnar Aug 04 '20 at 11:31
105

You can use the window object to get at it .

window['myVar']

window has a reference to all global variables and global functions you are using.

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
JohnP
  • 49,507
  • 13
  • 108
  • 140
  • 33
    And needless to say, this one is safer than eval(). – Cray Feb 25 '11 at 12:23
  • the `window` is look like `state`. that realy helpfull. – binpy Sep 01 '20 at 02:48
  • But how about when I want to use a local varaible? – Bu Saeed Apr 15 '22 at 19:20
  • 1
    @BuSaeed Not sure I understand, if the variable is already local scope, can't you just refer it to it by name? You should probably ask a new question as this is an old question with a different meaning. – JohnP Apr 16 '22 at 13:36
62

Just don't know what a bad answer gets so many votes. It's quite easy answer but you make it complex.

// If you want to get article_count
// var article_count = 1000;
var type = 'article';
this[type+'_count'] = 1000;  // in a function we use "this";
alert(article_count);
shkschneider
  • 17,833
  • 13
  • 59
  • 112
Terry Lin
  • 2,529
  • 22
  • 21
  • 15
    "in a function we use `this`" - If you want to access a _global_ variable in this way, it is better to be explicit and use the `window` object, not `this`. `this` is ambiguous. – MrWhite Aug 23 '15 at 23:25
  • 2
    But **inside of a function** you cannot use `this`, or anything else, to access the variable `type` from your example, if you have its name in another variable: `function test(vname) { var type = 'article'; this[vname] = 'something else'; alert(type); }; test('type')` will show `article`, not `something else`. And that is what the "complex answer" explains. – Orafu Jan 06 '20 at 18:36
  • 1
    This does not work. It outputs `undefined` to the alert box if you put it in a function and call it with an object (either with the `new` operator or with dot notation). – celticminstrel Jun 29 '20 at 00:24
  • Works great inside of Express.js routes – GavinBelson Jan 29 '21 at 01:47
  • Thanks @Terry, this works perfectly in Vue. When you have multiple data properties declared, and you want a method to decide which data property to target, you just pass the property name like this: `changeProperty(propertyName) { this[propertyName] = 1; } ` `changeProperty("bar")` `changeProperty("baz")` – DemiA Oct 23 '21 at 15:38
  • This might work in Express.js or Vue, but the original question was about JavaScript, generally. And in the general JS landscape there are tons of scenarios where this idea won't work. Not sure why the high number of upvotes... – Edward Munch Jul 06 '22 at 11:45
33

This is an example :

for(var i=0; i<=3; i++) {
    window['p'+i] = "hello " + i;
}

alert(p0); // hello 0
alert(p1); // hello 1
alert(p2); // hello 2
alert(p3); // hello 3

Another example :

var myVariable = 'coco';
window[myVariable] = 'riko';

alert(coco); // display : riko

So, the value "coco" of myVariable becomes a variable coco.

Because all the variables in the global scope are properties of the Window object.

Azodium
  • 1,785
  • 1
  • 13
  • 10
29
a = 'varname';
str = a+' = '+'123';
eval(str)
alert(varname);

Try this...

amitchd
  • 965
  • 5
  • 8
21

In Javascript you can use the fact that all properties are key value pairs. jAndy already mentioned this but I don't think his answer show how it can be exploited.

Usually you are not trying to create a variable to hold a variable name but are trying to generate variable names and then use them. PHP does it with $$var notation but Javascript doesn't need to because property keys are interchangeable with array keys.

var id = "abc";
var mine = {};
mine[id] = 123;
console.log(mine.abc);

gives 123. Usually you want to construct the variable which is why there is the indirection so you can also do it the other way around.

var mine = {};
mine.abc = 123;
console.log(mine["a"+"bc"]);
David Newcomb
  • 10,639
  • 3
  • 49
  • 62
  • 1
    var someJsonObj = {}; in a loop.... for(var i=0; i<=3; i++) { someJsonObj[i] = []; }, but i can be anything. so dynamically generated variables, all sit inside someJsonObj for easy reference. – rajeev Apr 07 '17 at 06:31
10

If you don't want to use a global object like window or global (node), you can try something like this:

var obj = {};
obj['whatever'] = 'There\'s no need to store even more stuff in a global object.';

console.log(obj['whatever']);
Brent Barbata
  • 3,631
  • 3
  • 24
  • 23
7

2019

TL;DR

  • eval operator can run string expression in the context it called and return variables from that context;
  • literal object theoretically can do that by write:{[varName]}, but it blocked by definition.

So I come across this question and everyone here just play around without bringing a real solution. but @Axel Heider has a good approaching.

The solution is eval. almost most forgotten operator. ( think most one is with() )

eval operator can dynamically run expression in the context it called. and return the result of that expression. we can use that to dynamically return a variable's value in function's context.

example:

function exmaple1(){
   var a = 1, b = 2, default = 3;
   var name = 'a';
   return eval(name)
}

example1() // return 1


function example2(option){
  var a = 1, b = 2, defaultValue = 3;

  switch(option){
    case 'a': name = 'a'; break;
    case 'b': name = 'b'; break;
    default: name = 'defaultValue';
  }
  return eval (name);
}

example2('a') // return 1
example2('b') // return 2
example2() // return 3

Note that I always write explicitly the expression eval will run. To avoid unnecessary surprises in the code. eval is very strong But I'm sure you know that already

BTW, if it was legal we could use literal object to capture the variable name and value, but we can’t combine computed property names and property value shorthand, sadly, is invalid

functopn example( varName ){
    var var1 = 'foo', var2 ='bar'

    var capture = {[varName]}

}

example('var1') //trow 'Uncaught SyntaxError: Unexpected token }`
pery mimon
  • 7,713
  • 6
  • 52
  • 57
6

I needed to draw multiple FormData on the fly and object way worked well

var forms = {}

Then in my loops whereever i needed to create a form data i used

forms["formdata"+counter]=new FormData();
forms["formdata"+counter].append(var_name, var_value);
Talha
  • 1,546
  • 17
  • 15
  • Thanks...It totally saved me ! this.$refs['listView' + index].nativeView.animate({..}) I needed vars inside refs like this.$refs.listView1 listView2 and so on... – Mehdi Nourollah Mar 01 '20 at 14:31
3

This is an alternative for those who need to export a dynamically named variable

export {
  [someVariable]: 'some value',
  [anotherVariable]: 'another value',
}

// then.... import from another file like this:
import * as vars from './some-file'

Another alternative is to simply create an object whose keys are named dynamically

const vars = { [someVariable]: 1, [otherVariable]: 2 };

// consume it like this
vars[someVariable];
JeanAlesi
  • 478
  • 3
  • 17
  • 1
    Why do you need to `import`/`export` to do that? Why not simply creating an object and accessing its properties? Also, it's **not** possible to export dynamic names, unless you export an object as default... – FZs Nov 12 '20 at 21:02
1

use Object is great too.

var a=123
var b=234
var temp = {"a":a,"b":b}
console.log(temp["a"],temp["b"]);
Steve Jiang
  • 653
  • 7
  • 17
1

Although this have an accepted answer I would like to add an observation:

In ES6 using let doesn't work:

/*this is NOT working*/
let t = "skyBlue",
    m = "gold",
    b = "tomato";

let color = window["b"];
console.log(color);

However using var works

/*this IS working*/
var t = "skyBlue",
    m = "gold",
    b = "tomato";

let color = window["b"];
console.log(color);

I hope this may be useful to some.

enxaneta
  • 31,608
  • 5
  • 29
  • 42
  • 2
    same applies to `const` –  Apr 19 '19 at 08:26
  • 1
    True. But you can create an object with the variables and select the variable from there: `const vars = { t, m, b }; console.log(vars['b'])`. Otherwise `eval` works too. – Fabian von Ellerts Oct 03 '19 at 14:41
  • @FabianvonEllerts what is the purpose of your comment? This answer only aims to address the difference between block-level scope (`let` & `const`) and global (`window`) scope (`var` & `function`). Your comment has nothing to do with that and rather serves as a separate answer. – Gust van de Wal Dec 14 '20 at 11:51
1

This will do exactly what you done in php:

var a = 1;
var b = 2;
var ccc = 3;
var name = 'a';
console.log( window[name] ); // 1
unbreak
  • 1,000
  • 1
  • 16
  • 32
1

Simplest solution : Create an array of objects that every object has two field (variableName,variableValue)

let allVariables = [];

for (let i = 0; i < 5; i++)
    allVariables.push({ variableName: 'variable' + i, variableValue: i * 10 });

for (let i = 0; i < allVariables.length; i++)
    console.log(allVariables[i].variableName + ' is ' + allVariables[i].variableValue);

OutPut :

variable0 is 0
variable1 is 10
variable2 is 20
variable3 is 30
variable4 is 40

console.log(allVariables) json :

 [
    {
        "variableName": "variable0",
        "variableValue": 0
    },
    {
        "variableName": "variable1",
        "variableValue": 10
    },
    {
        "variableName": "variable2",
        "variableValue": 20
    },
    {
        "variableName": "variable3",
        "variableValue": 30
    },
    {
        "variableName": "variable4",
        "variableValue": 40
    }
]
M Komaei
  • 7,006
  • 2
  • 28
  • 34
0

what they mean is no, you can't. there is no way to get it done. so it was possible you could do something like this

function create(obj, const){
// where obj is an object and const is a variable name
function const () {}

const.prototype.myProperty = property_value;
// .. more prototype

return new const();

}

having a create function just like the one implemented in ECMAScript 5.

Alfgaar
  • 172
  • 1
  • 7
0

eval() did not work in my tests. But adding new JavaScript code to the DOM tree is possible. So here is a function that adds a new variable:

function createVariable(varName,varContent)
{
  var scriptStr = "var "+varName+"= \""+varContent+"\""

  var node_scriptCode = document.createTextNode( scriptStr )
  var node_script = document.createElement("script");
  node_script.type = "text/javascript"
  node_script.appendChild(node_scriptCode);

  var node_head = document.getElementsByTagName("head")[0]
  node_head.appendChild(node_script);
}

createVariable("dynamicVar", "some content")
console.log(dynamicVar)
Axel Heider
  • 557
  • 4
  • 14
  • 2
    small improvement, it is better to use `var node_head = document.getElementsByTagName("head")[0]` instead of ID, as no one gives an `id="head"` to `` :-) – ddlab Nov 09 '14 at 17:41
  • I do :) But thanks, now I can finally remove this `id="head" thing – Axel Heider May 04 '15 at 11:33
  • 1
    This just seems to be an overly complex way of creating a global variable?! (...and how does this answer the question?) – MrWhite Aug 23 '15 at 23:39
  • genius :) eval is the solution. Even if your code does not work – pery mimon Jan 04 '19 at 18:27
-1

It is always better to use create a namespace and declare a variable in it instead of adding it to the global object. We can also create a function to get and set the value

See the below code snippet:

//creating a namespace in which all the variables will be defined.
var myObjects={};

//function that will set the name property in the myObjects namespace
function setName(val){
  myObjects.Name=val;
}

//function that will return the name property in the myObjects namespace
function getName(){
  return myObjects.Name;
}

//now we can use it like:
  setName("kevin");
  var x = getName();
  var y = x;
  console.log(y)  //"kevin"
  var z = "y";
  console.log(z); //"y"
  console.log(eval(z)); //"kevin"

In this similar way, we can declare and use multiple variables. Although this will increase the line of code but the code will be more robust and less error-prone.

Rishu Ranjan
  • 494
  • 4
  • 7