In a comment to my last entry, a reader said:
In C/C++/Java/C# statements must end with a semicolon. JavaScript OTOH allows the use of a newline as a statement separator. Presumably this was done so that it would be easier to use for scripters. Personally, I hate the ambiguities it generates.
I'm with you -- I find it irritating as well. But we're stuck with it now.
Let me clarify a bit what is actually going on here. The statement "a newline is a legal statement separator" is actually not the best way to think about this language feature. A better way to think about it is that JScript requires some statements to end in a semicolon but JScript will automatically insert missing semicolons. The net result of both statements is the same, but I find it easier to think about semicolons as required and the compiler as automatically fixing some mistakes.
First off, what statements require semicolons? The empty statement (yes, a single semicolon is a legal statement!), a var declaration, an expression evaluation, a do-while, continue, break, return and throw require semicolons.
The automatic semicolon inserter scans the program looking for places that semicolons are required but missing. It automatically inserts the semicolon provided that:
- the missing semicolon goes before a newline or a right-curly-brace or the end of the program.
- adding a missing semicolon does not create an empty statement.
- adding a missing semicolon does not screw up the arguments to the "for" loop.
This leads to a few bizarre situations, because programs like these are now hard to parse:
a
++
b
is that
a
++;
b;
or
a;
++
b;
? To disambiguate this, JScript restricts where newlines can go. You can't put a newline in the middle of a ++, --, return, throw, break or continue. For example, the automatic semicolon inserter turns this:
return
a++
into
return;
a++;
Auto semi insertion can bite you. Consider for example:
Number.prototype.blah = function(){ /* whatever */ }
var d = 1, e = 2
var a = d * e
(d + e).blah()
Auto semicolon insertion turns that into
Number.prototype.blah = function(){ /* whatever */ };
var d = 1, e = 2;
var a = d * e <-- no semi here!
(d + e).blah();
because of course
var a = d * e(d + e).blah();
is perfectly legal. Nonsensical at runtime but syntactically legal.
My advice is to use semicolons rather than relying upon the crazy rules for the auto semi inserter.