G
Garrett Smith
ASI - Automatic Semicolon Insertions
Semicolon is inserted in various places where a statement could be
terminated, but is not. General advice, taken from the specification,
with my own addition.
Semicolons
* A postfix ++ or -- operator should appear on the same line as its
operand.
* An Expression in a return or throw statement should start on the
same line as the return or throw token.
* An Identifier in a break or continue statement should be on the same
line as the break or continue token.
* Semicolons should appear explicitly where they are required.
The last one is my addition. It is debatable but generally true. What
follows a newline-ending expression determines whether the semicolon is
inserted or not.
The advice semicolons should appear explicitly where they are required
provides a general guideline that makes a program more resilient to
errors that could be introduced by minification or inadvertent changes
in source code whitespace, including whitespace in comments, and order
of expressions.
A FunctionExpression that is followed by a newline, then followed by
grouping operator, will be interpreted as a CallExpression, implicating
the FunctionExpression in the call. For example, if the developer wanted
to declare a MyWidget constructor, and then do some initializations in a
closure following it, he might use:
var MyWidget = function a(){
this.name = "mike";
}
/**
* Initialize Widget
*/
(function() {
/*...*/
});
- but the problem with that is that the FunctionExpression would be
called because the parentheses, which were intended to be a grouping
operator, were interpreted as a part of CallExpression, resulting in
MyWidget having the value undefined window.name getting the value
"mike", just as:
var MyWidget = function(){
this.name = "mike";
}(function(){});
- would have the same effect, more obviously.
Line terminators in comments may also affect ASI. If comment begins at
the end of an expression and it contains a line terminator, a semicolon
should be automatically inserted. Not all implementations will do that,
however.
For example:
var MyWidget = function a(){
return {toString: function(){return"widget"}};
}/*
*/g = 2;
Conforming implementations consider whitespace in comments and so the
program can run. JScript, however, does not run the program.
Consistent failure can be expected from:
var MyWidget = function(){
this.name = "mike";
}/** Initialize Widget */g = 2;
- because the comment following the FunctionExpression does not contain
a line terminator. If a line terminator is added, then the program
should be interpreted with a semicolon being automatically inserted
immediately following the FunctionExpression. As stated, not all
implementations do that.
From ES5, 5.1.2:
| A MultiLineComment (that is, a comment of the form /*...*/
| regardless of whether it spans more than one line) is likewise simply
| discarded if it contains no line terminator; but if a MultiLineComment
| contains one or more line terminators, then it is replaced by a single
| line terminator, which becomes part of the stream of input elements
| for the syntactic grammar.
Question: How does a MultiLineComment can span more than one line and
not contain a line terminator?
Regardless, the complexities of automatic semicolon insertion are
undesirable and should be avoided. The advice provided aims to help
avoid those problems.
Comments or suggestions?
Semicolon is inserted in various places where a statement could be
terminated, but is not. General advice, taken from the specification,
with my own addition.
Semicolons
* A postfix ++ or -- operator should appear on the same line as its
operand.
* An Expression in a return or throw statement should start on the
same line as the return or throw token.
* An Identifier in a break or continue statement should be on the same
line as the break or continue token.
* Semicolons should appear explicitly where they are required.
The last one is my addition. It is debatable but generally true. What
follows a newline-ending expression determines whether the semicolon is
inserted or not.
The advice semicolons should appear explicitly where they are required
provides a general guideline that makes a program more resilient to
errors that could be introduced by minification or inadvertent changes
in source code whitespace, including whitespace in comments, and order
of expressions.
A FunctionExpression that is followed by a newline, then followed by
grouping operator, will be interpreted as a CallExpression, implicating
the FunctionExpression in the call. For example, if the developer wanted
to declare a MyWidget constructor, and then do some initializations in a
closure following it, he might use:
var MyWidget = function a(){
this.name = "mike";
}
/**
* Initialize Widget
*/
(function() {
/*...*/
});
- but the problem with that is that the FunctionExpression would be
called because the parentheses, which were intended to be a grouping
operator, were interpreted as a part of CallExpression, resulting in
MyWidget having the value undefined window.name getting the value
"mike", just as:
var MyWidget = function(){
this.name = "mike";
}(function(){});
- would have the same effect, more obviously.
Line terminators in comments may also affect ASI. If comment begins at
the end of an expression and it contains a line terminator, a semicolon
should be automatically inserted. Not all implementations will do that,
however.
For example:
var MyWidget = function a(){
return {toString: function(){return"widget"}};
}/*
*/g = 2;
Conforming implementations consider whitespace in comments and so the
program can run. JScript, however, does not run the program.
Consistent failure can be expected from:
var MyWidget = function(){
this.name = "mike";
}/** Initialize Widget */g = 2;
- because the comment following the FunctionExpression does not contain
a line terminator. If a line terminator is added, then the program
should be interpreted with a semicolon being automatically inserted
immediately following the FunctionExpression. As stated, not all
implementations do that.
From ES5, 5.1.2:
| A MultiLineComment (that is, a comment of the form /*...*/
| regardless of whether it spans more than one line) is likewise simply
| discarded if it contains no line terminator; but if a MultiLineComment
| contains one or more line terminators, then it is replaced by a single
| line terminator, which becomes part of the stream of input elements
| for the syntactic grammar.
Question: How does a MultiLineComment can span more than one line and
not contain a line terminator?
Regardless, the complexities of automatic semicolon insertion are
undesirable and should be avoided. The advice provided aims to help
avoid those problems.
Comments or suggestions?