Given these four examples of defining an object and then attempting to immediately access their properties:
{foo: \'bar\'}.foo
// syntax error: unexpected_to
It's a matter of the "context", your first two examples are not object literals!
They are statement blocks, for example:
{ foo: 'bar' }
The above code is evaluated as a block, containing a labelled statement (foo
) that points to an expression statement (the string literal 'bar'
).
When you wrap it on parentheses, the code is evaluated in expression context, so the grammar matches with the Object Literal syntax.
In fact there are other ways to force the expression evaluation, and you will see that the dot property accesor notation works when applied directly to an object literal e.g.:
({foo:'bar'}.foo); // 'bar'
0, {foo:'bar'}.foo; // 'bar'
0||{foo:'bar'}.foo; // 'bar'
1&&{foo:'bar'}.foo; // 'bar'
// etc...
Now in your second example:
{foo: 'bar'}['foo']
What happens here is that the two statements are evaluated, first the block and then the expression statement that contains the Array literal.
Is a syntax ambiguity similar to what happens with function expressions vs function declarations.
See also:
It's not ignored, it's just not recognized as an object here.
{ ... }
at the start of a statement is parsed as a Block[spec] of code.
In the case of {foo: 'bar'}.foo
, the inner code foo: "bar"
is parsed as a LabelledStatement[spec].
So {foo: 'bar'}
parses correctly (even if it doesn't do what you expect) but the property access syntax is actually causing the syntax error, as accessing a property on a block is not valid.
As you noticed the solution is to enclose the object in parentheses:
({foo: 'bar'}).foo
Starting the statement with (
causes the parser to search for an expression inside of the parentheses. {foo: 'bar'}
when parsed as an expression is an Object Initializer[spec], as you expected.
For {foo: 'bar'}['foo']
, it's actually parsed as two separate statements: a block ({foo: 'bar'}
and an Array initializer (['foo']
):
{foo: 'bar'};
['foo'];