Search code examples
javascriptjavascript-objectslabeled-statements

Javascript Conflicting Syntax Between Function As Object Key And Labeled Function in Block


Assuming you have a browser that supports both labeled function declarations and block statements, what is the standard way/method for browsers to determine if the following is an object with a property named L that is function F, or a block that contains function F labeled as L:

{
    L: function F(){}
}

E.g.

To expose what I mean, here are two different copies of the above code modified to expose it as an array and as a function:

document.body.textContent = typeof( () => {
    L: function F(){}
} )

In the above code, the browser recognizes the arrow function notation and determines that it is a block statement. However,

document.body.textContent = typeof {
    L: function F(){}
}

The above code makes the browser think that it is an object written out as an object literal with index L being function F


Solution

  • You can reduce the question to: How does the browser know whether { starts a block and when does it start an object literal?

    And the answer to that is that JS engines will treat { as the start of a block if it appears in a statement position and as the start of an object literal if it is in an expression position.

    That's the reason why you have to add parenthesis (()) around {} when they appear in a statement position but you want an object instead.

    The introduction of labeled function declarations doesn't change the circumstances at all because the situation was already ambiguous:

    {
      foo: 42
    }
    

    Looking at the spec again, this ambiguity is actually pointed out:

    An ExpressionStatement cannot start with a U+007B (LEFT CURLY BRACKET) because that might make it ambiguous with a Block.

    (and the grammar reflects that too)