The following code illustrates an object literal being assigned, but with no semicolon afterwards:
var literal = {
say: function(msg) { alert(msg); }
}
literal.say("hello world!");
This appears to be legal, and doesn't issue a warning (at least in Firefox 3). Is this completely legal, or is there a strict version of JavaScript where this is not allowed?
I'm wondering in particular for future compatibility issues... I would like to be writing "correct" JavaScript, so if technically I need to use the semicolon, I would like to be using it.
Not technically, JavaScript has semicolons as optional in many situations.
But, as a general rule, use them at the end of any statement. Why? Because if you ever want to compress the script, it will save you from countless hours of frustration.
Automatic semicolon insertion is performed by the interpreter, so you can leave them out if you so choose. In the comments, someone claimed that
Semicolons are not optional with statements like break/continue/throw
but this is incorrect. They are optional; what is really happening is that line terminators affect the automatic semicolon insertion; it is a subtle difference.
Here is the rest of the standard on semicolon insertion:
For convenience, however, such semicolons may be omitted from the source text in certain situations. These situations are described by saying that semicolons are automatically inserted into the source code token stream in those situations.
The YUI Compressor and dojo shrinksafe should work perfectly fine without semicolons since they're based on a full JavaScript parser. But Packer and JSMin won't.
The other reason to always use semi-colons at the end of statements is that occasionally you can accidentally combine two statements to create something very different. For example, if you follow the statement with the common technique to create a scope using a closure:
var literal = {
say: function(msg) { alert(msg); }
}
(function() {
// ....
})();
The parser might interpret the brackets as a function call, here causing a type error, but in other circumstances it could cause a subtle bug that's tricky to trace. Another interesting mishap is if the next statement starts with a regular expression, the parser might think the first forward slash is a division symbol.
JavaScript interpreters do something called "semicolon insertion", so if a line without a semicolon is valid, a semicolon will quietly be added to the end of the statement and no error will occur.
var foo = 'bar'
// Valid, foo now contains 'bar'
var bas =
{ prop: 'yay!' }
// Valid, bas now contains object with property 'prop' containing 'yay!'
var zeb =
switch (zeb) {
...
// Invalid, because the lines following 'var zeb =' aren't an assignable value
Not too complicated and at least an error gets thrown when something is clearly not right. But there are cases where an error is not thrown, but the statements are not executed as intended due to semicolon insertion. Consider a function that is supposed to return an object:
return {
prop: 'yay!'
}
// The object literal gets returned as expected and all is well
return
{
prop: 'nay!'
}
// Oops! return by itself is a perfectly valid statement, so a semicolon
// is inserted and undefined is unexpectedly returned, rather than the object
// literal. Note that no error occurred.
Bugs like this can be maddeningly difficult to hunt down and while you can't ensure this never happens (since there's no way I know of to turn off semicolon insertion), these sorts of bugs are easier to identify when you make your intentions clear by consistently using semicolons. That and explicitly adding semicolons is generally considered good style.
I was first made aware of this insidious little possibility when reading Douglas Crockford's superb and succinct book "JavaScript: The Good Parts". I highly recommend it.
In this case there is no need for a semicolon at the end of the statement. The conclusion is the same but the reasoning is way off.
JavaScript does not have semicolons as "optional". Rather, it has strict rules around automatic semicolon insertion. Semicolons are not optional with statements like break, continue, or throw. Refer to the ECMA Language Specification for more details; specifically 11.9.1, rules of automatic semicolon insertion.
Use JSLint to keep your JavaScript clean and tidy
JSLint says:
Error:
Implied global: alert 2
Problem at line 3 character 2: Missing
semicolon.
}
The semi-colon is not necessary. Some people choose to follow the convention of always terminating with a semi-colon instead of allowing JavaScript to do so automatically at linebreaks, but I'm sure you'll find groups advocating either direction.
If you are looking at writing "correct" JavaScript, I would suggest testing things in Firefox with javascript.options.strict (accessed via about:config) set to true. It might not catch everything, but it should help you ensure your JavaScript code is more compliant.
This is not valid (see clarification below) JavaScript code, since the assignment is just a regular statement, no different from
var foo = "bar";
The semicolon can be left out since JavaScript interpreters attempt to add a semicolon to fix syntax errors, but this is an extra and unnecessary step. I don't know of any strict mode, but I do know that automated parsers or compressors / obfuscators need that semicolon.
If you want to be writing correct JavaScript code, write the semicolon :-)
According to the ECMAscript spec, http://www.ecma-international.org/publications/standards/Ecma-262.htm, the semicolons are automatically inserted if missing. This makes them not required for the script author, but it implies they are required for the interpreter. This means the answer to the original question is 'No', they are not required when writing a script, but, as is pointed out by others, it is recommended for various reasons.
Related
In Node.js's REPL (tested in SpiderMonkey as well) the sequence
var foo = null;
(foo) = "bar";
is valid, with foo subsequently equal to "bar" as opposed to null.
This seems counterintuitive because one would think the parenthesis would at least dereference bar and throw Invalid left-hand side in assignment`.
Understandably, when you do anything interesting it does fail in aforementioned way.
(foo, bar) = 4
(true ? bar : foo) = 4
According to ECMA-262 on LeftHandExpressions (so far as I can interpret) are no valid non-terminals that would lead to a parenthetical being accepted.
Is there something I'm not seeing?
It's valid indeed. You're allowed to wrap any simple assignment target in parenthesis.
The left hand part of the = operation is a LeftHandSideExpression as you correctly identified. This can be tracked down through the various precendence levels (NewExpression, MemberExpression) to a PrimaryExpression, which in turn might be a CoverParenthesizedExpressionAndArrowParameterList:
( Expression[In, ?Yield] )
(actually, when parsed with target PrimaryExpression, it's a ParenthesizedExpression).
So it's valid by the grammar, at least. Whether it's actually valid JS syntax is determined by another factor: early error static semantics. Those are basically prose or algorithmic rules that make some production expansions invalid (syntax errors) in certain cases. This for example allowed the authors to reuse the array and object initialiser grammars for destructuring, but only applying certain rules. In the early errors for assignment expressions we find
It is an early Reference Error if LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral and IsValidSimpleAssignmentTarget of LeftHandSideExpression is false.
We can also see this distinction in the evaluation of assignment expressions, where simple assignment targets are evaluated to a reference that can be assigned to, instead of getting the destructuring pattern stuff like object and array literals.
So what does that IsValidSimpleAssignmentTarget do to LeftHandSideExpressions? Basically it allows assignments to property accesses and disallows assignments to call expressions. It doesn't state anything about plain PrimaryExpressions which have their own IsValidSimpleAssignmentTarget rule. All it does is to extract the Expression between the parentheses through the CoveredParenthesizedExpression operation, and then again check IsValidSimpleAssignmentTarget of that. In short: (…) = … is valid when … = … is valid. It'll yield true only for Identifiers (like in your example) and properties.
As per #dlatikay's suggestion, following an existing hunch, research into CoveredParenthesizedExpression yielded a better understanding of what's happening here.
Apparently, the reason why a non-terminal cannot be found in the spec, to explain why (foo) is acceptable as a LeftHandExpression, is surprisingly simple. I'm assuming you understand how parsers work, and that they operate in two separate stages: Lexing and Parsing.
What I've learned from this little research tangent is that the construct (foo) is not technically being delivered to parser, and therefor the engine, as you might think.
Consider the following
var foo = (((bar)));
As we all know, something like this is perfectly legal. Why? Well you visually can just ignore the parenthesis while the statement remains making perfect sense.
Similarly, here is another valid example, even from a human readability perspective, because the parentheses only explicate what PEMDAS already makes implicit.
(3 + ((4 * 5) / 2)) === 3 + 4 * 5 / 2
>> true
One key observation can be loosely derived from this, given an understanding of how parsers already work. (remember, Javascript still is being parsed (read: compiled) and then run) So in a direct sense, these parentheses are "stating the obvious".
So all that being said, what exactly is going on?
Basically, parentheses (with the exception of function parameters) are collapsed into proper groupings of their containing symbols. IANAL but, in lay man's terms, that means that parentheses are only interpreted to guide the parser how to group what it reads. If the context of the parentheses is already "in order", and thus does not require any tweaking of the emitted AST, then the (machine) code is emitted as if those parentheses did not exist at all.
The parser is more or less being lazy, assuming the parens are impertinent. (which in this edge-case, is not true)
Okay, and where exactly is this happening?
According to 12.2.1.5 Static Semantics: IsValidSimpleAssignmentTarget in the spec,
PrimaryExpression: (CoverParenthesizedExpressionAndArrowParameterList)
Let expr be CoveredParenthesizedExpression of CoverParenthesizedExpressionAndArrowParameterList.
Return IsValidSimpleAssignmentTarget of expr.
I.E. If expecting primaryExpression return whatever is inside the parenthesis and use that.
Because of that, in this scenario, it does not convert (foo) into CoveredParenthesizedExpression{ inner: "foo" }, it converts it simply into foo which preserves the fact that it is an Identifier and thus syntactically, while not necessarily lexically, valid.
TL;DR
It's wat.
Want a little more insight?
Check out #Bergi's answer.
This question already has answers here:
Do you recommend using semicolons after every statement in JavaScript?
(11 answers)
Closed 6 years ago.
When executing a function in JavaScript, I've always ended my code block with a semi-colon by default, because that's what I've been taught to do. Coming from Java it felt a bit unorthodox at first, but syntax is syntax.
function semiColon(args) {
// code block here
};
or
function sloppyFunction(args) {
// code block here
}
Lately I've been seeing more and more code where the developer left the semi-colon out after functions, but the intended code still executed normally. So are they actually required? If not, why is it common practice to include them? Do they serve another purpose?
Function declarations do not need a semi-colon, though if you put a semi-colon there, it won't be harmful, it is just a redundant empty statement.
function semiColon(args) {
// code block here
};;;; // 4 empty statements
Most statements require a semi-colon, but if you leave the semi-colon out it will be inserted automatically in most cases by Automatic Semi-Colon Insertion, with caveats. In general it is easier to just always add a semi-colon after your statements, so that you, and other developers working with your code, don't have to worry about those caveats.
This code is correct:
function semiColon(args) {
// code block here
} // No need for semi-colon
var semiColon = function (args) {
// code block here
}; // Semi-colon required here
Whereas this code is wrong, but will still usually work:
function semiColon(args) {
// code block here
}; // Redundant unnecessary Empty Statement
var semiColon = function (args) {
// code block here
} // Semi-colon required here,
// but ASI will sometimes insert it for you, depending on
// the subsequent token
NO - using semicolons to end function declarations are NOT necessary in JavaScript. While they will not throw an error, they are the equivalent of using more than one semicolon to end a line of code - harmless, but unnecessary. Being superfluous, they are considered poor stylistic and programming practice.
The one exception is a function expression, e.g.
var my_function = function(a, b){ };
where you DO need the semicolon to terminate the line.
You shall not add a semicolon after a function declaration.
Because, after checking the Javascript grammar:
StatementList:
StatementListItem
StatementList
StatementListItem:
Statement
Declaration
Declaration:
HoistableDeclaration
ClassDeclaration
LexicalDeclaration
HoistableDeclaration:
FunctionDeclaration
GeneratorDeclaration
Here's the grammar production for a function:
FunctionDeclaration → HoistableDeclaration → Declaration → StatementListItem → StatementList
which proves that my former response is wrong (no need to look at the former edits, as it's wrong! ;) ).
A function xx() {} construct alone is a special case, neither — strictly speaking — a statement or an expression, and thus is NOT to be ended with a semicolon.
You only need to add a semicolon (or leave the ASI take care of it) if you're using the expression function() construct, which exists when it is part of a statement. To make it a statement you need to either have it part of a statement:
var foo = function() {};
or embedded within another expression:
(function() {})();
!function x() { ... }();
And in either cases, you need to add the semicolon at the end of the full statement, obviously.
Generally speaking, I like the python mantra "explicit is better than implicit" so when you hesitate to add a semicolon that the ASI would add otherwise, just add it.
sorry for being wrong in the first version of my answer, I'll debug some PHP code as a penitence. ☺
HTH
I have the following code:
class Car() {
constructor() {
// ...
}
withSemi() {
// ...
}; // ESLint does not complain here
withoutSemi() {
// ...
} // ESLint does not complain here
}; // ESLint will complain about this semicolon (no-extra-semi)
Can someone explain how the automatic semicolon insertion will work in ES6 in regards to classes and why ESLint has this behaviour?
According to the ECMAScript 2015 class specification, a semicolon is a valid ClassElement, so it can exist within a ClassBody.
However, its semantics treat it as having no behavior whatsoever (for example, see NonConstructorMethodDefinitions). Effectively you can have as many or as few semicolons you want in a ClassBody and it won't change a thing.
Automatic semicolon insertion actually doesn't come into play here, or as often as people think in general. Roughly speaking, ASI only happens when the parser sees something that wouldn't be allowed to be part of the previous block or line. (The actual rules for ASI aren't terribly long if you're interested; scroll down for examples and practical advice.) However in this context, you're allowed to put a bunch of class method definitions together sequentially. Thus there's nothing "unexpected" about the next method in the list, so no semicolon gets inserted between them.
I don't know the history of the decision, but I assume semicolons are valid ClassElements because they were already valid as empty statements, and it would probably be confusing for folks if you couldn't put semicolons in a class body.
In the lodash library line, why is there a defensive semicolon on the first line?
;(function(window) {
...
}(this));
I recently read in Definitive JavaScript about defensive semicolons being used to protect against users who don't use semicolons properly, but as there is no preceding code, I don't see the point. Is this in case the library is concatenated on to the end of another library?
In case you use a javascript compressor/minifier, and the previous plugin does not have a ; at the end, you might run into troubles. So, as a precaution, ; is added.
Also, It safely allows you to append several javascript files, to serve it in a single HTTP request.
That semicolon is also used to ensure that it is not interpreted as a continuation of the previous statement:
var x = 0 // Semicolon omitted here
;[x,x+1,x+2].forEach(console.log) // Defensive ; keeps this statement separate
More detail: https://stackoverflow.com/a/20854706/1048668
just started using JSLint on some code I bought some time ago. Its critsizing many lines of code... Whats your opinion on these lines? Should I rewrite them, and if so, how could these be fixed?
Problem at line 5 character 23: Use the array literal notation [ ]
var radios = new Array();
Problem at line 22: 'focustextareas' was used before it was defined
function focustextareas(){
Problem at line 125: Expected '===' and instead saw '=='
else if(elem.className=="optionsDivVisible") {elem.className = "optionsDivI...
Problem at line 133: Expected a conditional expression and instead saw an assignment
while(elem = document.getElementById("optionsDiv"+g))
Problem at line 136 character 13: Expected '{' and instead saw 'return'
return g;
Here are my opinions.
Using the literal [] notation is a good practice since it can avoid some confusing circumstances when using the constructor. Also, it's much shorter.
//var radios = new Array();
var radios = [];
The === uses a less complex algorithm and avoids some of the confusion that == can cause, so I'd use === whenever possible.
//else if(elem.className=="optionsDivVisible") {elem.className = "optionsDivI...
else if(elem.className==="optionsDivVisible") {elem.className = "optionsDivI...
I don't personally mind this one.
while(elem = document.getElementById("optionsDiv"+g))
I assume this one is the single statement for the previous while statement. I don't mind it, but at the same time, I don't think it is bad advice to say you should always place your statement in a Block {}.
return g;
You really should (if you haven't) read the docs for JSLint. The first sentence says: "JSLint will hurt your feelings."
JSLint was written by Doug Crockford and expresses his (very well founded) view of code quality and error prone coding. JSLint finds not only errors but as well "bad coding style". Crockford explains the reasoning behind JSLints suggestion in a very interesting video and in his book "JavaScript: The Good Parts".
JSLint is useful for pointing out common pitfalls in JavaScript and is especially useful for less experienced JavaScript developers. Some of it is sound, pretty much unarguably good advice. However, some of it represents only the views of its author, some of which are highly subjective. Here's my views on the examples you gave:
Problem at line 5 character 23: Use the array literal notation [ ]
Good advice. Array literals are shorter, safer and less ambiguous than using the Array constructor.
Problem at line 22: 'focustextareas' was used before it was defined
Good advice. JavaScript has both function declarations and function expressions, which behave differently in that functions created by function declarations are available in the whole scope in which they are defined whereas those created by function expressions do not. So the following works:
foo();
function foo() {}
... whereas the following does not:
foo(); // TypeError
var foo = function() {};
The problem here is that if you refactored a function declaration to a function expression, your code would stop working if that function was used before it was declared.
Problem at line 125: Expected '===' and instead saw '=='
else if(elem.className=="optionsDivVisible")
Questionable. No need to change. What this is trying to alert you to is that == does type coercion (the rules of which lead to some unintuitive results) whereas === does not. However, in this case both operands are guaranteed to be strings (so long as elem really is a DOM element), in which case === and == are specified to perform exactly the same steps and there is no advantage to using one over the other.
Problem at line 133: Expected a conditional expression and instead saw an assignment
while(elem = document.getElementById("optionsDiv"+g))
Good advice, but no need to change. I find this construction convenient and do use it, but it highlights a potential source of errors: if == or === was intended instead of = then this would not throw an error and lead to difficult-to-diagnose bugs.
Problem at line 136 character 13: Expected '{' and instead saw 'return'
return g;
Unsure. More code needed.
5: Use the array literal notation [ ] Many programmers prefer [] cause it's shorter.
22: 'focustextareas' was used before it was defined function may be used before its definition, but in some comlicated cases with closures, this would be a useful warning.
125: Expected '===' and instead saw '==' doesn't matter, class name is always a string.
133: Expected a conditional expression ... just a useful warning.
136: Expected '{' and instead saw 'return' hard to say. This message taken out from context look silly.