Semicolons must follow statements. They do not need to keep track of the blocks. For example, here is an unnecessary semicolon with if
:
if(foo === bar) {
A semicolon after an if
block if
never required.
What does this have to do with your case? Well, sometimes { ... }
is a block, and sometimes { ... }
is an object literal. The surrounding context allows the grammar to determine what it is. In your first case, this is an object; in the second case, it is a block.
The characters following the return
on the same line are parsed as an expression. When { ... }
parsed as an expression, it is an object literal. In your first example, return { ... }
is a return statement with an object expression. It must have a semicolon because it is a statement.
It is important to understand here that ECMAScript does not allow line breaks to separate return
and expression for the return value . This is in ES2015 & # xa7; 11.9.1, Rules for automatic semicolon insertion :
ReturnStatement [Yield] :
return
[no LineTerminator here] Expression ;
return
[no LineTerminator here] Expression [In ,? Yield] ;
ReturnStatement cannot have a LineTerminator character between return
and expression.
Since you have a newline between your return
and { ... }
, the { ... }
not parsed as belonging to return
. It is autonomous, which means that it is analyzed as a block. A sequence { ... }
can only be parsed as an object when it is part of a larger statement or expression, for example
foo = { ... }
- function argument (
bar({ ... }
) - return value (
return { ... }
) - and etc.
When { ... }
is purely on one line, it is treated as a block.
Since the second case has a block, not an object, it does not need a semicolon, as described at the beginning of this answer.