-1

very basic JavaScript programmer here!

I was busy on some code with variables that look like this:

blocktype1;
blocktype2;
blocktype3;
blocktype4;
... //everything between blocktype4 and blocktype70, the three dots are not actual code!
blocktype70;

Now I was using eval() in a function where a value was given to one of the blocktype variables. The blocktype depended on the variable "number".

This is what I had for that part:

eval("blocktype" + number) = 3

What I want is, say "number" is 27, then I want the variable blocktype27 to get a value of 3. When I check the console it says:

ReferenceError: Invalid left-hand side in assignment

Could anyone possibly help me? I would prefer just vanilla JavaScript and still the use of eval. Thank you for your time!

JReesW
  • 31
  • 9
  • 7
    Instead of that start using arrays. – zerkms Jun 29 '15 at 21:44
  • about that, i'm kinda in that noob stage where i can do specific things and arrays aren't really one of them. shame on me i know! – JReesW Jun 29 '15 at 21:45
  • 7
    Learn them, and run far, far away from `eval()`. – Paul Roub Jun 29 '15 at 21:45
  • 1
    Agreed. It's somewhat counterproductive to teach a new developer how to do this rather than teaching the proper way, namely arrays. – Joseph Marikle Jun 29 '15 at 21:46
  • I will, but for now I want to now how to do it like this – JReesW Jun 29 '15 at 21:46
  • you would need to put the whole expression in eval to do it like that: `eval('blocktype'+number+'=3')`. if the vars are global, `window["blocktype"+number]=3;` works – dandavis Jun 29 '15 at 21:46
  • So it's not really possible? – JReesW Jun 29 '15 at 21:47
  • nvr mind what i said – JReesW Jun 29 '15 at 21:48
  • 1
    It is possible. It's just that you will never want to do this because of the security concerns. – Joseph Marikle Jun 29 '15 at 21:48
  • 1
    http://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea – Paul Roub Jun 29 '15 at 21:49
  • @JosephMarikle: based on the description, there are no obvious security concerns with `eval` here... if in doubt, you could use `Number(number)` instead of just `number`, which is 100% safe – dandavis Jun 29 '15 at 21:50
  • Ok, but, forget everything about me not knowing enough, is it possible for me to do it with just eval and variables (not arrays)? – JReesW Jun 29 '15 at 21:50
  • @Paul Roub - I'm not planning to get it online so I'll just use eval() – JReesW Jun 29 '15 at 21:51
  • 1
    @dandavis I disagree. Not enough information was given to determine how `number` was filled. It could have been a `prompt()` call for all we know. – Joseph Marikle Jun 29 '15 at 21:51
  • @JosephMarikle: well if it came from a prompt, we _know_ it's not input from another user, and thus not a security concern. the devtools console is a lot easier way to self-hack... i don't think numbers, from the user or another user can be dangerous. – dandavis Jun 29 '15 at 21:52
  • @JosephMarikle number is determined by the player position (yes it's a game) minus 1. So it's just a number – JReesW Jun 29 '15 at 21:53
  • 1
    @dandavis the simple fact is that we don't know where it came from. That's the issue. Better to assume use of eval is a potential risk than assume it's entirely benign especially when variables of unknown origin are involved. – Joseph Marikle Jun 29 '15 at 21:55
  • @JosephMarikle: you're right, we don't know. we cannot say "you will never want to do this because of the security concerns", if we don't know there's a security concern present. this could be a one-device app. i agree "don't use eval" (it's slow), but never say never when talking about JS ;) ... if the OP is running "minus 1", we know the input must be sanitized and safe before it gets to `eval`, unless you know of a super wicked number-based XSS – dandavis Jun 29 '15 at 21:59
  • @dandavis I have no idea what you are talking about – JReesW Jun 29 '15 at 22:03
  • @JReesW: sorry, i meant that if you convert it to a number, you can eval any input without worry. for example, can you make an alert just by changing the value of `x` here: `var x="alert(123)"; eval(Number(x));` ? if you can, you have my deepest respect and admiration... – dandavis Jun 29 '15 at 22:07
  • @dandavis "minus 1" speaks to iteration. that says nothing about the initial value or if the manipulation of that variable occurs before or after the variable is used in eval. Again, another instance of we don't know enough. I did say "you will never want to do this" and it was poorly worded to be stating `eval` and it's security concerns to be the cause. My initial intent is that such a case (creating a bunch of variables where an array will suffice) will never be needed much less using eval. – Joseph Marikle Jun 29 '15 at 22:08
  • @JosephMarikle: that we can both agree on, good point! i should point out that since `json_encode` (php) and `JSON.stringify` (JS) came out, there's actually few XSS problems with eval, whereas malformed HTML can easily burn you... – dandavis Jun 29 '15 at 22:08

2 Answers2

1

The 'correct' solution would probably be to use an Array which is ideal for sequences and are accessible by index.

var number = 1;
var val = 3;
var blocktype = []; // so clean
blocktype[number] = val;

However, properties can be accessed as with the bracket notation as well. This assumes the variables are in global scope and are thus properties of the global (window) object.

var blocktype1;    // .. etc
window["blocktype" + number] = val;

The problem with the eval is that is effectively the same as doing f() = 3 which does not make sense: only variables/properties can be assigned to1.

However eval is a built-in function and the results of a function cannot be assigned to, per the error message. It could be written as

var blocktype1;    // .. etc (see dandavis' comment)
eval("blocktype" + number + " = " + val);
// What is actually eval'd is:
// eval("blocktype1 = 3")

which quickly exposes a flaw with eval. If val was the string "Hello world!" with would result in eval("blocktype1 = Hello world!") which is clearly invalid.


1 For the gritty: the left-hand side of an assignment has to be a Reference Specification Type, which is a more wordy way of describining the above behavior. (It is not possible for a JavaScript function to return a RST, although it could technically be done for vendor host objects.)

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • 1
    a risk with the eval pattern is in "use strict", assigning to an unknown var would throw when other updates work just fine... – dandavis Jun 29 '15 at 21:55
  • Thanks, the eval part helped, I'm sure the other part would have helped too, but I'm still too noob to understand what exactly is going on in the top part. Thanks again! – JReesW Jun 29 '15 at 22:10
  • @JReesW I recommend learning how to use arrays and property accessors. They are cleaner, teach important fundamentals, and will help avoid issues later. See the linked ["Why is using eval is a *bad* idea?"](http://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea?lq=1) question - with very few exceptions eval is simply unnecessary and messy. – user2864740 Jun 29 '15 at 22:13
0

Feel free not to accept this, since it's specifically not using eval(), but:

You can allocate an array of size 71 like so:

var blocktype = new Array(71);

(your number values apparently start at 1, so we'll have to ignore the first element, blocktype[0], and leave room for blocktype[70], the 71st)

You can now assign elements like this:

blocktype[number] = 3;   

and use them like so:

alert( blocktype[number] );
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • p.s. I know that `var blocktype = []` would be shorter, and the sizing isn't necessary, but it seemed useful to point out the zero-based indexing. – Paul Roub Jun 29 '15 at 21:56