Automatic semicolon insertion & return statements
The javascript interpreter/compiler is so smart to only insert automatic semicolons if afterwards there is valid Javascript.
Your code works, because && b
as it stands is no valid expression - that's why no semicolon gets inserted after the return a
resulting in:
return a && b && c;
However:
return (undefined);//implicitely inserted
{
....
}
is perfectly valid and thats why a semicolon gets inserted.
For completeness' sake the ref to the spec: automatic semicolon insertion. THe examples are worth reading through.
What are the rules for JavaScript's automatic semicolon insertion (ASI)?
First of all you should know which statements are affected by the automatic semicolon insertion (also known as ASI for brevity):
- empty statement
var
statement- expression statement
do-while
statementcontinue
statementbreak
statementreturn
statementthrow
statement
The concrete rules of ASI, are described in the specification §11.9.1 Rules of Automatic Semicolon Insertion
Three cases are described:
- When an offending token is encountered that is not allowed by the grammar, a semicolon is inserted before it if:
- The token is separated from the previous token by at least one
LineTerminator
. - The token is
}
e.g.:
{ 1
2 } 3
is transformed to
{ 1
;2 ;} 3;
The NumericLiteral
1
meets the first condition, the following token is a line terminator.
The 2
meets the second condition, the following token is }
.
- When the end of the input stream of tokens is encountered and the parser is unable to parse the input token stream as a single complete Program, then a semicolon is automatically inserted at the end of the input stream.
e.g.:
a = b
++c
is transformed to:
a = b;
++c;
- This case occurs when a token is allowed by some production of the grammar, but the production is a restricted production, a semicolon is automatically inserted before the restricted token.
Restricted productions:
UpdateExpression :
LeftHandSideExpression [no LineTerminator here] ++
LeftHandSideExpression [no LineTerminator here] --
ContinueStatement :
continue ;
continue [no LineTerminator here] LabelIdentifier ;
BreakStatement :
break ;
break [no LineTerminator here] LabelIdentifier ;
ReturnStatement :
return ;
return [no LineTerminator here] Expression ;
ThrowStatement :
throw [no LineTerminator here] Expression ;
ArrowFunction :
ArrowParameters [no LineTerminator here] => ConciseBody
YieldExpression :
yield [no LineTerminator here] * AssignmentExpression
yield [no LineTerminator here] AssignmentExpression
The classic example, with the ReturnStatement
:
return
"something";
is transformed to
return;
"something";
Can someone explain me how the empty statement in javaScript is affected from Automatic Semicolon Insertion
Read the spec linked from the MDN page. The empty statement is "affected" because ASI won't be done if the inserted semicolon would result in an empty statement.
Hand-wringing over when ASI happens can be dispensed with by simply including semicolons explicitly. The most common pitfall of ASI is the return
statement, when attempting something like
return
{ propertyName: "something" };
Don't do that. Start the object initializer on the same line as the return
.
As to the difference between a semicolon and an empty statement: a semicolon is a boundary. In the following code:
var x; ;
There's a var
declaration statement, then an empty statement. The second semicolon is not part of the empty statement, but it implies that there is an empty statement before it.
Javascript automatic semicolon insertion for do-while statements
I'm pretty sure that "case" added in ES2015 is only there to standardize rules which browsers had already implemented in order to be compatible with terribly-written (or weirdly minified) scripts. It wasn't exactly a new feature, so much as it was a tweak of the specification to be in line with what browsers were doing already.
For example, your snippet runs in IE11, which was released in 2013:
do {} while (false) var a = 42;console.log('no parse errors');
Why is JavaScript designed to automatically insert a semicolon after a return followed by a new line?
The exact reasons why are probably lost in the mists of time. I'm willing to bet that it happened something like this:
- At some point, somebody thought it would be a good idea to make semicolons optional at the end of statements.
- Later on, somebody else noticed an ambiguity in the syntax when semicolons were omitted when used with
return
statements in the way you describe. - The formal language specification was then amended with the confusing new rule about omitted semicolons on return statements, to codify current practice rather than changing the rules to make sense.
Why does a return statement on a new line not return any value?
The "rule" is automatic semicolon insertion.
return
is a valid statement all on its own, so it is treated as a complete statement. The code starting on the next line is also syntactically valid (although it's not interpreted as an object at all in this case, but rather a code block containing a label and a single "statement" that consists of a string literal). So automatic semicolon insertion kicks in here and the two are treated as separate statements.
The code that starts on the line after the return
is simply ignored.
Note that some IDEs and linters can help with this, since you essentially have unreachable code. Here is a screenshot of how VSCode's default syntax highlighting displays the two functions. You can see that the hello: world
is shaded a dull color in the second function:
Why does a multiline comment cause automatic semicolon insertion?
This is expected, it's working as designed. The ES6 specifiction says the following on the grammar for comments:
Comments behave like white space and are discarded except that, if a
MultiLineComment contains a line terminator code point, then the
entire comment is considered to be a LineTerminator for purposes of
parsing by the syntactic grammar.
And this LineTerminator then causes automatic semicolon insertion to kick in, following the usual rules.
Related Topics
How to Redirect to an External Url from Angular2 Route Without Using Component
How to Set the Prototype of a JavaScript Object That Has Already Been Instantiated
How to Load a JavaScript File Dynamically
Indirect Function Call in JavaScript
How to Use Nodejs to Open Default Browser and Navigate to a Specific Url
What Is Settimeout Doing When Set to 0 Milliseconds
Canvas Todataurl() Returns Blank Image
What's the Difference Between Reflow and Repaint
How to Remove Documents Using Node.Js Mongoose
Mobile Safari: JavaScript Focus() Method on Inputfield Only Works with Click
How to Give Keyboard Focus to a Div and Attach Keyboard Event Handlers to It
Difference and Intersection of Two Arrays Containing Objects
Why the Function Called by Settimeout Has No Callstack Limit
How to Turn Nan from Parseint into 0 for an Empty String
How to Define Setter/Getter on Prototype