Given these four examples of defining an object and then attempting to immediately access their properties:
{foo: 'bar'}.foo
// syntax error: unexpected_token
I expected this would return the value of ‘foo’, but it results in a syntax error.
The only explanation I can come up with is that the object definition hasn’t been executed and therefore is not yet an object. It seems that the object definition is therefore ignored and the syntax error comes from attempting to execute just:
.foo
// results in the same syntax error: unexpected_token
Similarly:
{foo: 'bar'}['foo']
// returns the new Array ['foo']
Which seems to be evidence that the object literal is ignored and the trailing code is executed.
These, however, work fine:
({foo: 'bar'}).foo
// 'bar'
({foo: 'bar'})['foo']
// 'bar'
The parentheses are used to run the line of code and since the result of that parenthetical operator is the instantiated object, you can access properties.
So, why is the object definition ignored and not executed immediately?
It’s a matter of the “context”, your first two examples are not object literals!
They are statement blocks, for example:
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.:
Now in your second example:
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: