'When does JS interpret {} as an empty block instead of an empty object?
I was reading the answer to this question (about the "wat" video) and it said:
{}+[]
This is interpreted as an empty block of code, unary plus and empty array. First part does nothing, array is converted to a comma-separated string of it's elements (empty string for empty array), then to a number (empty string is converted to 0), hence 0.
I am currently learning JS from "The Definitive Guide" so I try to really understand things like that.
My question is, when does JS decide to interpret {} as an empty block of code, instead of an empty object?
Also, there are some inconsistencies between Node.js and Firebug which I would like to understand.
Firebug:
![Firebug console output for <code>{}[]</code> and <code>({}[])</code>](https://i.stack.imgur.com/4JnaG.png)
Node.js:
![Node.js output for <code>{}[]</code> and <code>({}[])</code>](https://i.stack.imgur.com/KqbIH.png)
Solution 1:[1]
Let's look at the language grammar, shall we? Section 12, Statements:
Statement :
Block
VariableStatement
EmptyStatement
ExpressionStatement
...lots of other stuff...
That's a very fancy way of saying that a statement can be a block, a variable statement, an empty statement, an expression statement, or lots of other stuff. Notice that the first option there is a 'Block':
Block :
{ StatementList(opt) }
StatementList :
Statement
StatementList Statement
Which is again, a fancy way of saying that a block is a {, optionally followed by a bunch of statements, followed by a }.
And that's what you see in your example: Before the JavaScript parser thinks that what you have could be an object literal (which is defined somewhere under ExpressionStatement, the 4th thing a 'Statement' could be), it first thinks that you have a 'Block'.
Edit: If you want, you can see it live in a JavaScript engine's source code:
- In V8, Chrome's JavaScript engine, we go into
Parser::ParseStatement. The first thing it checks is whether we're on a{, and if it does, parses as block. - In SpiderMonkey, Firefox's JavaScript engine, we go from
Parser::statementto again see the first check being against a{and parsing it as a block statement.
Regarding your second question, that's been covered to great detail on this question. To summarise in a sentence: Node.js treats your input as if it were an expression (thus it can't be a 'Block'), while Firebug/Chrome dev tools treat it like a 'Statement'.
Solution 2:[2]
When the first token in a new statement is {, then {} is interpreted as an empty block.
(Actually of course when { appears after the header clause of something like if or while, then {} is an empty block too, but that's not the interesting case.)
Thus in any other context, like say an argument to a function:
foo({});
the {} is interpreted as an empty object literal.
This situation is similar to the way in which the function keyword is treated differently when it's the first thing in a statement. The syntax has ambiguity, and the parser solves the problem with fixed rules.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Community |
| Solution 2 |
