JSLint The Javascript debugger: Should I debug these issues? - javascript

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.

Related

I don't understand one liner if else statement in javascript. Can anyone explain? [duplicate]

I once heard that leaving the curly braces in one-line statements could be harmful in JavaScript. I don't remember the reasoning anymore and a Google search did not help much.
Is there anything that makes it a good idea to surround all statements within curly braces in JavaScript?
I am asking, because everyone seems to do so.
No
But they are recommended. If you ever expand the statement you will need them.
This is perfectly valid
if (cond)
alert("Condition met!")
else
alert("Condition not met!")
However it is highly recommended that you always use braces because if you (or someone else) ever expands the statement it will be required.
This same practice follows in all C syntax style languages with bracing. C, C++, Java, even PHP all support one line statement without braces. You have to realize that you are only saving two characters and with some people's bracing styles you aren't even saving a line. I prefer a full brace style (like follows) so it tends to be a bit longer. The tradeoff is met very well with the fact you have extremely clear code readability.
if (cond)
{
alert("Condition met!")
}
else
{
alert("Condition not met!")
}
There's a readability aspect - in that when you have compound statements it can get very confusing. Indenting helps but doesn't mean anything to the compiler/interpreter.
var a;
var b;
var c;
//Indenting is clear
if (a===true)
alert(a); //Only on IF
alert(b); //Always
//Indenting is bad
if (a===true)
alert(a); //Only on IF
alert(b); //Always but expected?
//Nested indenting is clear
if (a===true)
if (b===true)
alert(a); //Only on if-if
alert (b); //Always
//Nested indenting is misleading
if (a===true)
if (b===true)
alert(a); //Only on if-if
alert (b); //Always but expected as part of first if?
//Compound line is misleading
//b will always alert, but suggests it's part of if
if (a===true) alert(a);alert(b);
else alert(c); //Error, else isn't attached
And then there's an extensibility aspect:
//Problematic
if (a===true)
alert(a);
alert(b); //We're assuming this will happen with the if but it'll happen always
else //This else is not connected to an if anymore - error
alert(c);
//Obvious
if (a===true) {
alert(a); //on if
alert(b); //on if
} else {
alert(c); //on !if
}
The thinking goes that if you always have the brackets then you know to insert other statements inside that block.
The question asks about statements on one line. Yet, the many examples provided show reasons not to leave out braces based on multiple line statements. It is completely safe to not use brackets on one line, if that is the coding style you prefer.
For example, the question asks if this is ok:
if (condition) statement;
It does not ask if this is ok:
if (condition)
statement;
I think leaving brackets out is preferable because it makes the code more readable with less superfluous syntax.
My coding style is to never use brackets unless the code is a block. And to never use multiple statements on a single line (separated by semicolons). I find this easy to read and clear and never have scoping issues on 'if' statements. As a result, using brackets on a single if condition statement would require 3 lines. Like this:
if (condition) {
statement;
}
Using a one line if statement is preferable because it uses less vertical space and the code is more compact.
I wouldn’t force others to use this method, but it works for me and I could not disagree more with the examples provided on how leaving out brackets leads to coding/scoping errors.
Technically no but very recommended!!!
Forget about "It's personal preference","the code will run just fine","it has been working fine for me","it's more readable" yada yada BS. This could easily lead to very serious problems if you make a mistake and believe me it is very easy to make a mistake when you are coding(Don't belive?, check out the famous Apple go to fail bug).
Argument: "It's personal preference"
No it is not. Unless you are a one man team leaving on mars, no. Most of the time there will be other people reading/modifying your code. In any serious coding team this will be the recommended way, so it is not a 'personal preference'.
Argument: "the code will run just fine"
So does the spaghetti code! Does it mean it's ok to create it?
Argument: "it has been working fine for me"
In my career I have seen so many bugs created because of this problem. You probably don't remember how many times you commented out 'DoSomething()' and baffled by why 'SomethingElse()' is called:
if (condition)
DoSomething();
SomethingElse();
Or added 'SomethingMore' and didn't notice it won't be called(even though the indentation implies otherwise):
if (condition)
DoSomething();
SomethingMore();
Here is a real life example I had. Someone wanted to turn of all the logging so they run find&replace "console.log" => //"console.log":
if (condition)
console.log("something");
SomethingElse();
See the problem?
Even if you think, "these are so trivial, I would never do that"; remember that there will always be a team member with inferior programming skills than you(hopefully you are not the worst in the team!)
Argument: "it's more readable"
If I've learned anything about programming, it is that the simple things become very complex very quickly. It is very common that this:
if (condition)
DoSomething();
turns into the following after it has been tested with different browsers/environments/use cases or new features are added:
if (a != null)
if (condition)
DoSomething();
else
DoSomethingElse();
DoSomethingMore();
else
if (b == null)
alert("error b");
else
alert("error a");
And compare it with this:
if (a != null) {
if (condition) {
DoSomething();
}
else {
DoSomethingElse();
DoSomethingMore();
}
} else if (b == null) {
alert("error b");
} else {
alert("error a");
}
PS: Bonus points go to who noticed the bug in the example above.
There is no maintainability problem!
The problem with all of you is that you Put semicolons everywhere. You don't need curly braces for multiple statements. If you want to add a statement, just use commas.
if (a > 1)
alert("foo"),
alert("bar"),
alert("lorem"),
alert("ipsum");
else
alert("blah");
This is valid code that will run like you expect!
There is no programming reason to use the curly braces on one line statements.
This only comes down to coders preferences and readability.
Your code won't break because of it.
In addition to the reason mentioned by #Josh K (which also applies to Java, C etc.), one special problem in JavaScript is automatic semicolon insertion. From the Wikipedia example:
return
a + b;
// Returns undefined. Treated as:
// return;
// a + b;
So, this may also yield unexpected results, if used like this:
if (x)
return
a + b;
It's not really much better to write
if (x) {
return
a + b;
}
but maybe here the error is a little bit easier to detect (?)
It's a matter of style, but curly braces are good for preventing possible dangling else's.
Always found that
if(valid) return;
is easier on my eye than
if(valid) {
return;
}
also conditional such as
(valid) ? ifTrue() : ifFalse();
are easier to read (my personal opinion) rather than
if(valid) {
ifTrue();
} else {
ifFalse();
}
but i guess it comes down to coding style
There are lots of good answers, so I won’t repeat, except as to say my “rule” when braces can be omitted: on conditions that ‘return’ or ‘throw’ (eg.) as their only statement. In this case the flow-control is already clear that it’s terminating:
Even the “bad case” can be quickly identified (and fixed) due to the terminating flow-control. This concept/structure “rule” also applies to a number of languages.
if (x)
return y;
always();
Of course, this is also why one might use a linter..
Here is why it's recommended
Let's say I write
if(someVal)
alert("True");
Then the next developer comes and says "Oh, I need to do something else", so they write
if(someVal)
alert("True");
alert("AlsoTrue");
Now as you can see "AlsoTrue" will always be true, because the first developer didn't use braces.
I'm currently working on a minifier. Even now I check it on two huge scripts. Experimentally I found out:
You may remove the curly braces behind for,if,else,while,function* if the curly braces don't include ';','return','for','if','else','while','do','function'. Irrespective line breaks.
function a(b){if(c){d}else{e}} //ok
function a(b){if(c)d;else e} //ok
Of course you need to replace the closing brace with a semicolon if it's not followed by on other closing brace.
A function must not end in a comma.
var a,b=function()c; //ok *but not in Chrome
var b=function()c,a; //error
Tested on Chrome and FF.
There are many problems in javascript. Take a look at JavaScript architect Douglas Crockford talking about it The if statement seems to be fine but the return statement may introduce a problem.
return
{
ok:false;
}
//silent error (return undefined)
return{
ok:true;
}
//works well in javascript
Not responding the question directly, but below is a short syntax about if condition on one line
Ex:
var i=true;
if(i){
dosomething();
}
Can be written like this:
var i=true;
i && dosomething();
I found this answer searching about a similar experience so I decided to answer it with my experience.
Bracketless statements do work in most browsers, however, I tested that bracketless methods in fact do not work in some browser.
As of February 26th 2018, this statement works in Pale Moon, but not Google Chrome.
function foo()
return bar;
I would just like to note that you can also leave the curly braces off of just the else. As seen in this article by John Resig's.
if(2 == 1){
if(1 == 2){
console.log("We will never get here")
}
} else
console.log("We will get here")
The beginning indentation level of a statement should be equal to the number of open braces above it. (excluding quoted or commented braces or ones in preprocessor directives)
Otherwise K&R would be good indentation style. To fix their style, I recommend placing short simple if statements on one line.
if (foo) bar(); // I like this. It's also consistent with Python FWIW
instead of
if (foo)
bar(); // not so good
If I were writing an editor, I'd make its auto format button suck the bar up to the same line as foo, and I'd make it insert braces around bar if you press return before it like this:
if (foo) {
bar(); // better
}
Then it's easy and consistent to add new statements above or below bar within the body of the if statement
if (foo) {
bar(); // consistent
baz(); // easy to read and maintain
}
No, curly braces are not necessary, However, one very important reason to use the curly brace syntax is that, without it, there are several debuggers that will not stop on the line inside the if statement. So it may be difficult to know whether the code inside the if statement ran without altering the code (some kind of logging/output statements). This is particularly a problem when using commas to add multiple lines of execution. Without adding specific logging, it may be difficult to see what actually ran, or where a particular problem is. My advice is to always use curly braces.
Braces are not necessary.....but add them anyway^
....why should you add braces in if statements if they are not necessary? Because there's a chance that it could cause confusion. If you're dealing with a project with multiple people, from different frameworks and languages, being explicit reduces the chances of errors cropping up by folks misreading each other's code. Coding is hard enough as it is without introducing confusion. But if you are the sole developer, and you prefer that coding style, then by all means, it is perfectly valid syntax.
As a general philosophy: avoid writing code, but if you have to write it, then make it unambiguous.
if (true){console.log("always runs");}
if (true) console.log("always runs too, but what is to be gained from the ambiguity?");
console.log("this always runs even though it is indented, but would you expect it to?")
^ Disclaimer: This is a personal opinion - opinions may vary. Please consult your CTO for personalized coding advice. If coding headaches persist, please consult a physician.
Please do write like this if you do if ifs:
if(a===1) if(b===2) alert(a);
alert(b);
Sometimes they seem to be needed! I couldn't believe it myself, but yesterday it occurred to me in a Firebug session (recent Firefox 22.0) that
if (! my.condition.key)
do something;
executed do something despite my.condition.key was true. Adding braces:
if (! my.condition.var) {
do something;
}
fixed that matter. There are myriards of examples where it apparently works without the braces, but in this case it definitely didn't.
People who tend to put more than one statement on a line should very definitely always use braces, of course, because things like
if (condition)
do something; do something else;
are difficult to find.
There is a way to achieve multiple line non curly braces if statements.. (Wow what english..) but it is kinda tedius:
if(true)
funcName();
else
return null;
function funcName(){
//Do Stuff Here...
}

Why is `(foo) = "bar"` legal in JavaScript?

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 Cover­Parenthesized­Expression­And­Arrow­Parameter­List:
( 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 Covered­Parenthesized­Expression 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.

Why does Google Closure Compiler optimize with null==a instead of a==null? [duplicate]

This question already has an answer here:
Why does Google Closure swap arguments?
(1 answer)
Closed 8 years ago.
So I use the Google Closure Compiler to minify my JavaScript before using it in production. Today, I paid attention to how it minifies and optimizes(?) the code and realized this trend:
Compiling the code below :
function b(a) {
if ( a == null ) {
console.log('ohai');
}
}
resulted in an optimization in the comparison expression where the literal is moved to the left and the variable to the right. As in
function b(a){null==a&&console.log("ohai")}
(Btw, it subsitutes single quotes for double quotes.) The expression remains the same if the other operand is an object. Why is moving the literal to the left of the operator an optimization of the expression?
There's no optimisation improvement (EDIT: possibly a hasty statement, DCoder's comment for e.g. is valid), but you could make the argument that it's just prudent practice.
For example, a programmer might accidentally use a single = instead of == - resulting in assignment instead of an equality check.
The following code would silently evaluate with no error:
var a = null;
function b(a){a=null&&console.log("ohai")} // notice the single =
b(a); // nothing
However, the way google does it, it produces an error in the console (tested in Chrome):
var a = null;
function b(a){null=a&&console.log("ohai")} // notice the single =
b(a); // produces error Uncaught ReferenceError: Invalid left-hand side in assignment
Hence, using null as the left-hand side makes these kind of user errors easier to spot.

Dynamic vs Inline RegExp performance in JavaScript

I stumbled upon that performance test, saying that RegExps in JavaScript are not necessarily slow: http://jsperf.com/regexp-indexof-perf
There's one thing i didn't get though: two cases involve something that i believed to be exactly the same:
RegExp('(?:^| )foo(?: |$)').test(node.className);
And
/(?:^| )foo(?: |$)/.test(node.className);
In my mind, those two lines were exactly the same, the second one being some kind of shorthand to create a RegExp object. Still, it's twice faster than the first.
Those cases are called "dynamic regexp" and "inline regexp".
Could someone help me understand the difference (and the performance gap) between these two?
Nowadays, answers given here are not entirely complete/correct.
Starting from ES5, the literal syntax behavior is the same as RegExp() syntax regarding object creation: both of them creates a new RegExp object every time code path hits an expression in which they are taking part.
Therefore, the only difference between them now is how often that regexp is compiled:
With literal syntax - one time during initial code parsing and
compiling
With RegExp() syntax - every time new object gets created
See, for instance, Stoyan Stefanov's JavaScript Patterns book:
Another distinction between the regular expression literal and the
constructor is that the literal creates an object only once during
parse time. If you create the same regular expression in a loop, the
previously created object will be returned with all its properties
(such as lastIndex) already set from the first time. Consider the
following example as an illustration of how the same object is
returned twice.
function getRE() {
var re = /[a-z]/;
re.foo = "bar";
return re;
}
var reg = getRE(),
re2 = getRE();
console.log(reg === re2); // true
reg.foo = "baz";
console.log(re2.foo); // "baz"
This behavior has changed in ES5 and the literal also creates new objects. The behavior has also been corrected in many browser
environments, so it’s not to be relied on.
If you run this sample in all modern browsers or NodeJS, you get the following instead:
false
bar
Meaning that every time you're calling the getRE() function, a new RegExp object is created even with literal syntax approach.
The above not only explains why you shouldn't use the RegExp() for immutable regexps (it's very well known performance issue today), but also explains:
(I am more surprised that inlineRegExp and storedRegExp have different
results.)
The storedRegExp is about 5 - 20% percent faster across browsers than inlineRegExp because there is no overhead of creating (and garbage collecting) a new RegExp object every time.
Conclusion:
Always create your immutable regexps with literal syntax and cache it if it's to be re-used. In other words, don't rely on that difference in behavior in envs below ES5, and continue caching appropriately in envs above.
Why literal syntax? It has some advantages comparing to constructor syntax:
It is shorter and doesn’t force you to think in terms of class-like
constructors.
When using the RegExp() constructor, you also need to escape quotes and double-escape backslashes. It makes regular expressions
that are hard to read and understand by their nature even more harder.
(Free citation from the same Stoyan Stefanov's JavaScript Patterns book).
Hence, it's always a good idea to stick with the literal syntax, unless your regexp isn't known at the compile time.
The difference in performance is not related to the syntax that is used is partly related to the syntax that is used: in /pattern/ and RegExp(/pattern/) (where you did not test the latter) the regular expression is only compiled once, but for RegExp('pattern') the expression is compiled on each usage. See Alexander's answer, which should be the accepted answer today.
Apart from the above, in your tests for inlineRegExp and storedRegExp you're looking at code that is initialized once when the source code text is parsed, while for dynamicRegExp the regular expression is created for each invocation of the method. Note that the actual tests run things like r = dynamicRegExp(element) many times, while the preparation code is only run once.
The following gives you about the same results, according to another jsPerf:
var reContains = /(?:^| )foo(?: |$)/;
...and
var reContains = RegExp('(?:^| )foo(?: |$)');
...when both are used with
function storedRegExp(node) {
return reContains.test(node.className);
}
Sure, the source code of RegExp('(?:^| )foo(?: |$)') might first be parsed into a String, and then into a RegExp, but I doubt that by itself will be twice as slow. However, the following will create a new RegExp(..) again and again for each method call:
function dynamicRegExp(node) {
return RegExp('(?:^| )foo(?: |$)').test(node.className);
}
If in the original test you'd only call each method once, then the inline version would not be a whopping 2 times faster.
(I am more surprised that inlineRegExp and storedRegExp have different results. This is explained in Alexander's answer too.)
in the second case, the regular expression object is created during the parsing of the language, and in the first case, the RegExp class constructor has to parse an arbitrary string.

Are semicolons needed after an object literal assignment in JavaScript?

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.

Categories

Resources