Why are programmers afraid of not using semicolons in JavaScript?
programmers.stackexchange.com
programmers.stackexchange.com
foo()
[1,2,3].forEach(bar)
Automatic semicolon insertion wouldn't work here, because the bracket could be a continuation of the last line. The same goes for parentheses at the beginning of a line.Source: http://blog.izs.me/post/2353458699/an-open-letter-to-javascr...
where it wil think i( is a function call.
There's the reason.
Comparing Python's handling of semicolons with JavaScript's ASI, you get the following:
-- End of statements
Python and JavaScript: Ends with either a new line or a semicolon.
-- Line joining
Python: whitespace strict, so lines must be either explicitly joined through the `\' escape character, or put inside a parenthesized expression, which ignores whitespace.
JavaScript: non-whitespace strict, so lines don't need to be explicitly joined. Statements may be continued by starting the following line with a continuation token (one of: `[ ( + - /')
-- Exceptions
Python: Parenthesized expressions use a different parser state (ie.: whitespace strict vs non-whitespace strict)
JavaScript: restricted production grammar usually have optional expressions following them, and since they are a valid statement on their own, the statement will be ended with a new line. So, the related information must start in the same line.
Restricted productions are: return, break and continue; Post-fix and prefix operators are included as restricted productions for readability's sake.
I fail to see how that's difficult to remember, or how that's insanely more complex than Python's rules...
return
{ foo: bar }returnStmt ::= "return" [ expression ] (";" or EOL)
Note that expression is optional, so it's the choice of `return' by itself being a valid statement on its own that "causes problems".
Plus, this is not really a problem that can be solved by simply putting semicolons everywhere. You can't change the parser rules by including or not semicolons.
Also, same thing with break/continue:
breakStmt ::= "break" [ label ] (";" or EOL)
continueStmt ::= "continue" [ label ] (";" or EOL)
A standalone object literal would likely be interpreted as a block and would throw a syntax error unless it were a simple identifier and a statement `{ foo: <statement> }`, in which case it would not interpret it as an object but exactly what it is, a label and a statement.
This is why JSON parsers which use eval must first wrap the object literal with parens, to make it an expression rather than a statement.
The thing is:
- `return` alone is a valid statement in its own.
- The parser just need to use a simple lookahead to decide whether the next line is part of the previous statement.
- The parser DON'T change the meaning of your programs.
All that's beside that is a matter of taste. Whether use semicolons or not is up to what sits better with each person. I'm just arguing against the silly and incorrect "technical" arguments against it.
"When you have a single statement, that stretches out over more than one line, but those lines are legal statements on their own, then it won't work like you want it to"
I would guess that the number of statements that stretch out over many lines are a very small part of the overall number of statements for most code.
But it just seems like most developers think that javascript might insert semicolons all over the place. Which it won't, the rules are clear once you learn them.
Best article I've read on the subject: http://inimino.org/~inimino/blog/javascript_semicolons
1. Prefix lines that start with punctuation, specifically [(-+/ with a ;. Then omit them everywhere else. Lines that start with punctuation are a tiny subset of all lines generally.
2. Postfix every line with a ;, "just in case"
I can't see how nr. 1 is harder. And in case 2 you don't actually put ; at the end of every line, you don't put them after {} blocks for example, so it's not like it's somehow easier to remember.
"Because we're used to doing it that way" is a reason I guess, but not a great one in my opinion.
// 1.
MyClass.prototype.myMethod = function() {
return 42;
} // No semicolon here.
(function() {
// Some initialization code wrapped in a function to create a scope for locals.
})();
There are at least two potential solutions here: 1) put a semicolon after every function declaration, and 2) put a semicolon before every self-executing function. Both work fine. Either way, you have to remember to put a semicolon somewhere, right? No difference in cognitive load. And if you say that #1 is easier to remember because it's more C-like, you've just blown your cover. You don't actually write C at your day job, do you? Because otherwise you'd realize that C does not require semicolons after functions. [normalVersion, ffVersion][isIE]();
Same thing. Just put a semicolon before lines that start with arrays like this. Also this code is crap. -1 == resultOfOperation() || die();
OK hold up, who really writes this stuff? Is this what code looks like at Google? Forget semicolons for a second and let's work on basic code readability. Explain the line aloud. "If resultOfOperation returns negative one, then die." Now write it. if (resultOfOperation() == -1) die();
Sweet, now people can read our code without juggling operator precedence rules in their head. Minor side effect: the semicolon issue goes away. return
{ foo: bar }
Really? Why oh why would you write such a thing and expect it to return the object?There, you've just fixed all the cases that are likely to go wrong.
Since JS source "feels" more C-like than Python-like to me, I think the semicolons are a good idea.
Won't you consider it? Less line noise, you know?
The capital letter in English is a strong visual indicator that a new sentence is starting. In code I think the line break does that more than well enough, no need for the ;
Also, JS was not designed from start as semicolon-less language. If you prefer semicolon-less JS - use Coffee Script. Otherwise it is very hard to debug such code for someone who do not expect semicolon-less JS code.
If you want good example, say "shell script" instead.
The (increasingly common) practice on minifying is just one offspring of that history, which is, to the main point, not shared with Python.
Problem at line 1 character 10: Expected ';' and instead saw '(end)'.Writing clear code is superior to writing "cute" code, and "return i++" is a case of the latter. In any case where the increment actually matters you are directly affecting a shared state and such changes should be made contextually obvious to the state of the object--one's neck would need to be very, very beard to think that this is immediately obvious and apparent in a contextually valid way.
Similarly, for many programmers, myself included, a semicolon is read as a period is in English--the end of the statement. (You keep saying that "but people don't get annoyed at Python when it does it," and guess what? I certainly get annoyed at it--Python consistently frustrates me because I find it considerably less readable.) Omitting semicolons is less immediately clear than including them and, again, can be misconstrued. Only it can be misconstrued by the program interpreter, too. (Oops.)
But when you write Python code, do you then end every line with a ; ? To make it more readable for yourself?
Consistency is important, and the Python community has essentially said "don't use semicolons." The JavaScript community has essentially said "use semicolons aggressively". I write code according to those idioms so other people are able to more easily use it.
while (word = getNextWord()) {
doSomething(word)
if (i > limit) return
i++
}
Sure, this can be written better but a semi-colon after "return" makes it less ambiguous."That's a stupid question to ask. More appropriate would be: who on earth thinks that omitting semi-colons makes anything worse?"