1

In Chrome 63.0 and Firefox 58.0, it appears that adding an index to an object literal prevents the object from being parsed as an object.

{"a":"b"}
17:37:32.246 {a: "b"}

{"a":"b"}["a"]
17:37:36.578 VM288:1 Uncaught SyntaxError: Unexpected token :

Can anybody explain why the parser doesn't parse this the way I do? (I think there must be a bug in my implementation of the spec...) It seems to think it's not parsing an object.

Surrounding the object in brackets results in syntactically correct expression:

({"a":"b"})["a"]
17:42:03.993 "b"
user234461
  • 1,133
  • 12
  • 29
  • What sense would it make to create an object just for the sake of immediately referencing a property of that object? – Mulan Jan 31 '18 at 17:51
  • @naomik If the index were a variable rather than a literal, then the object literal could serve as a look up table. This can be more expressive than repeated `if` statements or nested ternaries. – user234461 Jan 31 '18 at 17:52
  • In such a case you would pre-define the look-up table so that it can be re-used in the functions that reference it – where `myTable[myVar]` syntax is perfectly valid (no parentheses are needed). Using object literal syntax to create the look-up table every time it's needed would be wasteful. – Mulan Jan 31 '18 at 17:56
  • @naomik - no, setting it to a variable where it will needlessly take up memory and get garbage collected anyway is wasteful. – I wrestled a bear once. Jan 31 '18 at 17:58
  • I always encourage people to challenge the language they're using, but replacing `if`/`?:`/`switch` with a *dynamically-allocated* object literal is ignorant – it demonstrates a lack of general knowledge and awareness of how these language primitives *should* be used. If the OP posts code where this expression is used, it gives others the opportunity to show how to deal with such problems in a more effective way. It's a classic [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) where the question is nothing about JS's syntax, but about making dynamic choices. – Mulan Jan 31 '18 at 18:16
  • @naomik My use of a literal as a lookup table is indeed incidental to the question. Well spotted. Doesn't make it an XY problem - it's only an issue because of your objection to my use of the language. I don't consider this objection valid on the grounds you've given: worrying about dynamically allocated memory outside of hot functions in JavaScript sounds like premature optimisation, and indexing the literal directly is much terser. I personally find it more readable. Do you have a source for this being an unusual idiom? If so then feel free to argue on those grounds and I might listen. – user234461 Jan 31 '18 at 18:25
  • You won't receive opposition from me by writing unconventional JavaScript. However without seeing the surrounding program, I can't say much more than this is a [code smell](https://en.wikipedia.org/wiki/Code_smell), sorry. – Mulan Jan 31 '18 at 18:49

2 Answers2

4

{"a":"b"}["a"] - {} is detected as bracket body or block - not an object. Lets look an example on if statement, you can have something like this

if(condition) {
   "a": "b"
}

So actually you get an statement like "a" : "b" which is invalid.

({"a":"b"})["a"] - () evaluates the expression inside it, so {} is detected as object

Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112
4

It has to do with the console evaluating the {} as a block instead of an object literal.

This question is similar to "Defining a JavaScript object in console" and "Is the curly brackets object notation valid in any expression?" question on StackOverflow.

The key part from the spec is:

ExpressionStatement: [lookahead ∉ {{, function}] Expression ;

NOTE: An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.

romellem
  • 5,792
  • 1
  • 32
  • 64
  • I was going to mark this as a duplicate of the first question you linked to. But it appears that the problem described there doesn't even occur. You can type an object literal by itself in the console, but get the syntax error only when you try to index it (with either `.` or `[]`). – Barmar Jan 31 '18 at 18:02
  • 1
    Additionally, the reason why entering `{a: 1}` directly into the console no longer throws an error is related to "[Chrome devtools now automatically wrap everything that begins with `{` and ends with `}` in an implicit pair of parentheses](https://stackoverflow.com/a/36438289/864233)". This can be see by this [Chromium diff](https://chromium.googlesource.com/chromium/src.git/+/4fd348fdb9c0b3842829acdfb2b82c86dacd8e0a%5E!/#F2). – romellem Jan 31 '18 at 18:06
  • I had a feeling it was due to a console change. – Barmar Jan 31 '18 at 18:08
  • Accepted. Thanks for the answer! (It was a tight race with many twists and turns over the course of a couple of minutes, but in the end you quoted the spec. Congratulations to all who answered.) – user234461 Jan 31 '18 at 18:31