10

Please refer to the code below, when I "comment in" either of the commented out lines, it causes the error (in IE) of "':' expected". So then is my conclusion correct, that this inability to provide a reference to an object value, as an object key in a string literal; is this strictly an interpreter/parsing issue? Is this a candidate for an awful (or at least "bad") "part" of Javascript, in contrast to Crockford's "good parts"?

<script>
var keys = {'ONE': 'one'};

//causes error:
//var obj1 = {keys.ONE: 'value1'};
//var obj1 = {keys['ONE']: 'value1'};

//works
var obj1 = {};
obj1[keys.ONE] = 'value1';

//also works
var key_one = keys.ONE;
var obj2 = {key_one: 'value1'};
</script>
Dexygen
  • 12,287
  • 13
  • 80
  • 147
  • 1
    BTW `var key_one = keys.ONE; var obj2 = {key_one: 'value1'};` does not work as you expect it does. `obj2` s property will be `key_one` and not the the value of `key.ONE` thus not `one`. – RoToRa May 20 '10 at 11:29
  • 1
    Note that although the last example works, it creates an object with the property `key_one`, not the property `keys.One`. The variable `key_one` is irrelevant to the literal object in the next line. – Guffa May 20 '10 at 11:30
  • got it....that could be confusing....it should either disallow all "unquoted" strings, or de-reference the references, whatever they may be – Dexygen May 20 '10 at 11:35
  • 1
    They are already disallowed in JSON specs. But javascript objects can have methods defined as `{somevar: 1, methodname:function(){ /*stuff*/ } }` and I suppose somebody didn't like putting his methodname in quotes ;) – naugtur May 20 '10 at 11:44
  • @George: Alternatively they could have disallowed quoted names in object literals, like some other languages... – Guffa May 20 '10 at 11:47
  • And if You don't use quotes the parser wont let You call Your method "..." which is possible with quotes `var obj={"...":function(){}}` and You can call it `obj["..."]();`. fun, huh? :) – naugtur May 20 '10 at 11:47
  • possible duplicate of [Using a variable for a Javascript object key](http://stackoverflow.com/questions/2274242/using-a-variable-for-a-javascript-object-key) – Bergi Jul 24 '13 at 17:38

4 Answers4

15

The limitation of the literal object syntax is that the names has to be literal. As the names can be specified as an identifer as well as a string, it's not possible to use a variable instead.

This will create an object with a property n, not a property answer:

var n = 'answer';
var o = { n: 42 };
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Numeric literals are valid property names as well. Also, in ES5, the names can be specified as an identifier name (i.e., not just identifiers, but also reserved words). See http://stackoverflow.com/a/9568622/96656. – Mathias Bynens Mar 06 '12 at 09:23
6

You cannot use variables as keys when defining object with {}

Therefore they are being interpreted as string names and can consist only of characters avaliable for variable names

the

objectname[anythingThatReturnsValue]='value1'; is the way to go.

ALSO

You can generate a string and parse it

var s='{"'+keys.ONE+'": "value1"}';
var obj=JSON.parse(s);
//or
s='var obj2='+s;
eval(s);

Both above methods are bad practices for creating objects in JavaScript and I don't recommend them.

naugtur
  • 16,827
  • 5
  • 70
  • 113
  • You CAN use variables as keys when defining objects with {}, see the second "also works" block. – Dexygen May 20 '10 at 11:28
  • 1
    @George: No, you can't. The code runs, but it does not use the variable in the literal object. – Guffa May 20 '10 at 11:31
  • @George: He means its a `syntax error` and there isn't anything you can do about it :) – Salman A May 20 '10 at 11:31
  • 2
    @George - to be clear: `var obj2 = {key_one: 'value1'};` is the same as `var obj2 = {"key_one": 'value1'};` - key_one will be the name of the field. – naugtur May 20 '10 at 11:34
  • @George: Clarifying Guffa's reply: The `key_one` in in the second "also works" example *is* the name of the key; if you examine the object, it will have a property called "key_one", *not* "one" as it would if the *value* of `key_one` were being used when you created the literal. – T.J. Crowder May 20 '10 at 11:35
  • @naugtur: For JSON, I think you may have to also quote the key `var s = '{" + keys.ONE + '":"value1"}';` – vol7ron Jun 04 '12 at 21:30
  • Didn't mean to bring up an old answer, just saw this passing by :) – vol7ron Jun 06 '12 at 13:15
2

Think about it: if it were to work the way you want it would totally introduce a language ambiguity.

var obj = {something:"red"}
var obj = {"something":"red"}

The two statements are equivalent in JavaScript, because bareword keys are "autoquoted." So if something means the literal string "something", how it could also refer to the variable "something". It can't. So if you want to use variables they have to go in square bracket notation instead of key : value notation.

jpsimons
  • 27,382
  • 3
  • 35
  • 45
1

You can try:

var obj = {};
var val = 'foo';

obj[val] = 'bar'; 

obj.foo >>> 'bar';
Aamir Afridi
  • 6,364
  • 3
  • 42
  • 42