In the console of both FF and Chrome, {} is considered undefined until explicitly evaluated:
{};     // undefined
({});   // ▶ Object
Actually, it's a bit less defined than undefined -- it's apparently bad syntax:
{} === undefined;  // SyntaxError: Unexpected token ===
{}.constructor;    // SyntaxError: Unexpected token .
But not if it's on the other side, in which case it's fine:
"[object Object]" == {}.toString(); // true
Or if it's not the first expression:
undefined + undefined; // NaN
{} + undefined;        // NaN
undefined + {};        // "undefined[object Object]"
What gives?
If you use the curly brackets by themselves, it's not an object literal, it's a code block. As the code block doesn't contain any code, evaluating it results in undefined.
Okay, here is my answer. There is nothing new here. I am just linking to (a pretty copy of) the ECMAScript specification for the grammar and showing a few productions to show "why" it parses the way it does. In any case, the behavior is well-defined according to the JavaScript/ECMAScript grammar rules: {} is parsed differently depending upon the "context" it is in.
The JavaScript REPLs ("consoles") start to parse the code in the Statement grammar production or "statement context". (This is actually a lie, it starts at the Program or SourceElements production, but that adds additional constructs to dig through.) Here is a rough grammar breakdown with simplifications and omissions; see the link above for more:
Statement
    Block
    ...
    ExpressionStatement
Block
    # This is actually { StatementList[optional] }, but this is what
    # it amounts to: * means "0 or more".
    { Statement* }
ExpressionStatement
    # An ExpressionStatement can't start with "{" or "function" as
    # "{" starts a Block and "function" starts a FunctionStatement.
    [lookahead ∉ {{, function}]Expression ;
Expression
    # This is really PrimaryExpression; I skipped a few steps.
    ...
    ( Expression )
Thus (when in "statement context"):
   {}
-> Block  # with no StatementList (or "0 statements")
-> Statement
And:
   ({})
-> (Expression)
-> Expression
-> ExpressionStatement  # omitted in productions below
-> Statement
This also explains why undefined === {} parses as EXPR === EXPR -> EXPR -> STMT and results in false when evaluated. The {} in this case is in an "expression context".
In the case of {} === undefined it is parsed as {}; === undefined, or BLOCK; BOGUS -> STMT; BOGUS, which is a Syntax Error. However, with the addition of parenthesis this changes: ({} === undefined) is parsed as (EXPR === EXPR) -> (EXPR) -> EXPR -> STMT.
In the case of {} + "hi" it is parsed as {}; + "hi", or BLOCK; + EXPR -> STMT; EXPR -> STMT; STMT, which is valid syntax even though it is silly (+ is unary in this case). Likewise, just as above, "hi" + {} puts the {} into an "expression context" and it is parsed as EXPR + EXPR -> EXPR -> STMT.
The JavaScript console is just showing the result of the last Statement, which is "undefined" (well, "nothing" really, but that doesn't exist) for an empty {} block. (This might vary between browsers/environments as to what is returned in this case, e.g. last ExpressionStatement only?)
Happy coding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With