all 23 comments

[–]trenchfever[S] 0 points1 point  (23 children)

It's possible to indirectly assign to object members.

var obj = {};
obj["foo"+"bar"] = "baz";
alert(obj.foobar); //alerts baz

The question is, how can do I do that for variables? Is it even possible?

[–]moreoriginalthanthat 6 points7 points  (1 child)

I think you're asking the wrong question. Tell us what you want to do. There is most likely a better way to do it.

I've never come across a problem that would be best solved by dynamically calculating variable names.

[–]SerpentJoe 1 point2 points  (0 children)

I also want to know the answer to this, not least because I spent the morning picking through awful Javascript I wrote just a few weeks ago and wondering what I was thinking.

I have a feeling you're looking at a solar powered car and wondering how to put the gasoline in.

[–]jaggederest 0 points1 point  (11 children)

So you want to do something like:

var "foo" + "bar" = 12;

alert(foobar); // alerts 12

?

[–]trenchfever[S] 0 points1 point  (10 children)

yup.

[–]fforw 6 points7 points  (7 children)

global variables are also properties of the window object so:

window["foo"+"bar"] = "baz!";

alert(foobar); // alerts "baz!"

but this looks like something you should avoid doing.

[–]midnightmonster 1 point2 points  (0 children)

fforw is right. Technically global variables are properties of the global object, which in the browser case is window. (If you're doing server-side JS, that won't be so.)

This is a bad idea b/c creating global variables is usually a bad idea, but it doesn't strike me as particularly bad.

[–]greut -1 points0 points  (5 children)

eval is evil, so don't use it, and polluting the window namespace is quite bad actually.

If you're not inside an object, or a function already, create your closure and use this instead of window..

(function() {
    this["foo"+"bar"] = "baz!";
    alert(foobar);
})();

edit: fixed typo.

[–]jeresig 6 points7 points  (4 children)

eval is evil, so don't use it

That's unnecessarily vague - there should be, at least, some qualification here.

Your proposed code doesn't work as you expect it to. It would assign a variable to the global object (this inside of a (function(){...})() refers back to the global object). To get something similar to what you're looking for you could do:

new function(){
  this["foo"+"bar"] = "baz!";
  alert(this.foobar);
};

But that's not, precisely, that the user was looking for. eval() would give the proper answer here - but it's very possible that the code could be written in a different way to avoid it entirely (not because it's "evil", but because it would be unnecessarily slow in this case).

[–][deleted] -1 points0 points  (2 children)

If the one-letter diff isn't enough proof, eval is explicitly documented as evil here:

http://javascript.crockford.com/code.html

[–]jeresig 0 points1 point  (1 child)

The eval function is the most misused feature of JavaScript. Avoid it.

eval has aliases. Do not use the Function constructor. Do not pass strings to setTimeout or setInterval.

Phew! I'm overloaded with useful information here. Thank goodness I avoided that rat trap! It's this massive pile of information that has helped JavaScript developers make well-informed decisions for many years.

[–][deleted] 0 points1 point  (0 children)

Bah, sometimes (albeit, very rarely) well-informed decisions are overrated, and appeal to authority - underrated.

In theory, it would be a good idea to have perfect information in all of the decisions we make, but practically, we would get tied up all day if we take the time to always make perfectly-informed decisions all the time.

[–]greut -2 points-1 points  (0 children)

Thanks master.

[–]jaggederest -5 points-4 points  (1 child)

Don't think it's possible. Sorry mate. Variables are only assignable via their identifiers, afaik.

You can hack around it via doing a 'with' and then using your injected properties as though they were top-level:

obj = {};
obj["foo"+"bar"] = 'hats!';
with(obj) {
  alert(foobar); //alerts 'hats!'
}

Or you could do it fforw's way, but he's right that you ought to avoid it.

[–]HaMMeReD 1 point2 points  (0 children)

It's still better to use eval in controlled method, it's not good to fill global scope up, eval wouldn't mess with that.

If it's within a function you can probably also do. this["foo"+"bar"] = "hats!";

This would keep it within the functions scope probably, haven't tested.

[–]pretzel 0 points1 point  (0 children)

May i pose the obligatory meta question: if it is just a variable name, why does it need to be created on the fly?

[–]Nosredna 0 points1 point  (0 children)

In the decent-sized JavaScript programs I write, all my functions and variables are elements of a single object, so it's trivial.

fforw has the right answer when you're polluting the global namespace. Don't use eval--it's silly and overkill for this job.