43

Javascript has a feature called Automatic Semicolon Insertion where basically if the parser encounters an invalid token, and the last token before that was a line break, then the parser will insert a semicolon where the linebreak is. This enables you to basically write all your javascript code without semicolons, but you have to be aware of some edge cases, mostly if you have a return keyword and then the value you want to return on a new line.

function test(){
    // This will return 'undefined', because return is a valid statement
    // and  "john" is a valid statement on its own.
    return 
          "john"
}

Because of these gotchas there are dozens of articles with titles like 'Automatic semicolon insertion is Evil', 'Always use semicolons in Javascript' etc.

But in Python no one ever uses semicolons and it has exactly the same gotchas.

def test():
    # This will return 'undefined', because return is a valid statement
    # and  "john" is a valid statement on its own.
    return 
    "john"

Works exactly the same, and yet no-one is deadly afraid of Pythons behaviour.

I think the cases where the javascript behaves badly are few enough that you should be able to avoid them easily. Return + value on a new line? Do people really do that a lot?

What are considered the best practices? Do you use semicolons in javascript and why?

9
  • 3
    It doesn't work exactly the same. The semicolon insertion does not go wherever the newline is, necessarily, in JavaScript. See the second example on this Wikipedia page. The semicolon is not inserted where the newline is in that example.
    – Reid
    Commented Aug 7, 2011 at 15:42
  • 2
    My point wasn't that using semicolons and not using them worked exactly the same, the point was that the edge cases in javascript and python were the same. There certainly are a few edge cases where you have to know what's happening. Best article I've read on the subject: inimino.org/~inimino/blog/javascript_semicolons Commented Aug 7, 2011 at 15:46
  • 4
    I put semicolons in JavaScript for same reason I use periods in sentences. Sure the interpreter can usually make sense of your statements without them but its just bad form.
    – JD Isaacks
    Commented Aug 7, 2011 at 16:28
  • 3
    You might consider writing valid python in your examples. The comment indicator is #, not `//'. Commented Aug 7, 2011 at 16:46
  • 2
    "explicit is always better than implicit"
    – user7519
    Commented Aug 7, 2011 at 19:19

13 Answers 13

65

The reason is that in Python, newlines are an unambiguous way of separating code lines; this is by design, and the way this works has been thoroughly thought through. As a result, python code is perfectly readable and unambiguous without any special end-of-statement markers (apart from the newline).

JavaScript, on the other hand, was designed with a C-like syntax in mind, where statements are always terminated with a semicolon. To make the language more tolerant to errors, it tries to guess where extra semicolons should go to make the code correct. Since this was sort of retro-fitted onto the C-like syntax, it doesn't always work as expected (sometimes, the script interpreter guesses wrong), and can make for fairly counter-intuitive code.

Or, arguing in terms of "explicit is better than implicit": In Python, a newline is already completely explicit, while in JavaScript, it is ambiguous, so you add the semicolon to make it explicit.

10
  • 3
    Oh, and you can put code in comments using backquotes.
    – tdammers
    Commented Aug 7, 2011 at 14:18
  • 1
    A good example of a case where automatic semi-colon insertion will end up doing unexpected stuff is this : pastebin.com/aVeWGdya
    – HoLyVieR
    Commented Aug 7, 2011 at 15:50
  • 6
    In python, the rules are fairly simple: statements end at linebreaks unless there is an unclosed multiline string (""", '''), an unclosed dict ({}), an unclosed list ([]), or a backslash immediately before the linebreak. In javascript, the rules are significantly more complicated. Commented Aug 7, 2011 at 16:50
  • 7
    Covering 99% of errors is a good way to leave behind only the really hard to find ones. Its okay to leave them behind in python because there are easy rules that cover 100% of problems. Commented Aug 7, 2011 at 19:09
  • 2
    @Aaron: You forgot "an unclosed set of parentheses ( () )". (Not strictly "an unclosed tuple" because parentheses aren't just used for tuples.)
    – JAB
    Commented Aug 8, 2011 at 15:24
30

There is a pretty fundamental difference from the way it works in Python, I think. Quoting from the post Einar Egilsson linked to: "a semicolon is not implied at the end of a line if the first token of the subsequent line can be parsed as part of the same statement".

In Python a line break always ends the statement, except in certain fairly obvious cases such as within a parenthesized expression. JavaScript, on the other hand, will try to parse as many lines as it can before ending the statement, potentially leading to things like this:

// Define a function and name it area.
area = function(r) {
    return r * r * 3.14159
}

// Fooled you! We're actually invoking it.
(14)
1
  • 9
    Now here's a fun twist on this one. Replace 14 with something like (a + 1) ? do_something() : do_something_else(); and suddenly, area is set to the return value of do_something() or do_something_else() and you're left mightily confused.
    – Reid
    Commented Aug 7, 2011 at 23:10
21

I do often minimize my JS-Files in production mode. Means, removing comments and linebreaks.

Without the use of semicolons, that would break my Javascript.

7
  • 9
    OK, that's valid. But if your minimizer is an actual parser it could insert them again as necessary. Or just not remove the linebreaks, => you keep the linebreaks, lose the semicolons, they're roughly the same number so there's nothing lost. Commented Aug 7, 2011 at 13:55
  • 2
    @Einar Egilsson Closure Compiler indeed does this.
    – seriousdev
    Commented Aug 7, 2011 at 15:42
  • 2
    All things being equal, a newline is the same number of bytes as a semicolon. Your minimizer may strip all new lines, but then requires there to be semicolons. It's an even exchange. Commented Aug 7, 2011 at 17:19
  • 4
    @Logan: That's assuming one byte newlines, of course ;-)
    – Cameron
    Commented Aug 7, 2011 at 17:36
  • 1
    Of course, if we used Python instead of Javascript, we'd have to code WAY less to do the same thing, so the fact that semi-colons use a few bytes less than indentation is a moot point. Commented Aug 8, 2011 at 7:11
7

It does not work as you describe.

Javascript has a feature called Automatic Semicolon Insertion where basically if the parser encounters an invalid token, and the last token before that was a line break, then the parser will insert a semicolon where the linebreak is.

This is wrong. Example:

return
  1 + 2;

1 is a perfectly valid token, but the parser will still insert a semicolon directly after return.

As you see, even you can't tell exactly where a semicolon will happen.

The problem with automatic insertion is twofold:

  • For one, people might leave off a semicolon where the automatic insertion can't determine that one needs to be inserted.
  • Also, a semicolon might get inserted where it is not intended, as above.

Of course, using semicolons after every statement helps only with the first source of errors.

In any case, as you might guess by now, I believe that automatic semicolon insertion in C-like syntax is a bad idea.

4
  • 1
    ECMA Script spec explicitly specifies which cases a semi-colon will be inserted, so your line "You can't tell exactly where a semicolon will happen" is incorrect. The issue is that it is unintuitive in some cases, making it harder to teach someone who doesn't understand how it works.
    – zzzzBov
    Commented Aug 7, 2011 at 16:18
  • 1
    @zzzzBov: Yes, there is an exact specification, but does anyone really have all cases in mind while coding? Are you sure? Programmers are lazy, and rightfully so; they don't want to have to remember a complicated rule when a much simpler one would do. So they try to get around having to remember it.
    – Svante
    Commented Aug 7, 2011 at 16:25
  • I agree that semi-colon insertion is largely unnecessary. I'm just saying there's a difference between saying "you have no idea where semi-colons are going" and "the spec for semi-colon insertion is an unintuitive jumble"
    – zzzzBov
    Commented Aug 7, 2011 at 16:30
  • 1
    @Svante: But the return example shows us that we have to know these rules anyway. There you used a semicolon but it didn't help you do what you wanted. So, given that the language has this feature, we have the option of (1) Writing semicolons everywhere and knowing the rules so we understand what will happen (2) Not writing semicolons everywhere, and understanding the rules so we understand what will happen. Given that choice I think I'd rather skip the semicolons Commented Aug 7, 2011 at 17:06
4

I'd state one simple reason:

Javascript looks "kinda java-ish" or "kinda C-ish". Of course it's a dynamic language so it looks different... but face it - There are braces. Languages with braces generally have semicolons. The natural reflexes kick in and make your finger go towards the semicolon key before you hit Enter.

Python, on the contrary, even at a glance looks totally different. Hence, little or no analogy to "the standard boring languages" is intuitively formed and when one enters the "python mode", the lack of semicolons comes as natural.

3

There are a number of good reasons not to use semi-colon insertion in JavaScript.

Primarily it's because semi-colon insertion as defined in the ECMAScript standard is unintuitive for some cases. @Svante points out a case for return where the newline usage will cause issues.

What he doesn't mention is that it'll cause issues if you're using semi-colons as well, because semi-colon insertion happens whether you want it or not.

Another very good reason not to use semi-colon insertion is output control. In many cases JavaScript is run through a minifier before being used in production. Some minifiers may handle automatic semi-colon insertion cases, but I see no reason to rely on it working perfectly

Additionally for content management systems, inline JavaScript may be auto-minified, and I've seen a number of cases where the auto-minifier simply removes comments and trims whitespace (including newlines) from the beginning and end of each line.

For authors who don't have a choice of what tools are being chosen, it's much easier to just stick to a format that works in the vast majority of cases.

2
  • Ah, sorry, but regarding your third paragraph, I do mention that in my second-to-last sentence. :)
    – Svante
    Commented Aug 7, 2011 at 16:46
  • Yes, the tooling issue is valid (although good minifiers should handle this, e.g. Closure compiler). But in my opinion, we need to know these rules anyway, to avoid things like the 'return' example. And once I know the rules, I might as well use the feature, especially since it makes the code (IMO) more readable. Commented Aug 7, 2011 at 17:13
2

Not using semicolon is a recipe for failure when you minify your files JavaScript files. That is why I am scared of it.

2

In Javascript, you can write a program that would be syntactically correct in the absence of automatic semicolon insertion, and ASI will transform that program into a different syntactically correct program (for example, transforming code that returns a value into code that returns nothing). There is no analogous case in Python. In Python any newline that can end a statement will end a statement, unless it is escaped with a backslash. Technically, I suppose that Javascript's rules are equally deterministic, but I don't know if you could summarize Javascript's rules for ending statements in a single sentence.

2

In most cases JavaScript's ASI handles things as expected. One example of ASI perhaps not behaving the way you'd expect is this:

var i = 0

(function() {
   // do something
})()

This will be interpreted as calling the function 0 with the anonymous function, then executing the result. In this case you probably wanted to do an assignment, then immediately execute the anonymous function.

To someone not familiar with ASI it can be very confusing when you run into problems like this, so I always recommend developers on my team to use semicolons.

(As an aside: I don't use semicolons when working on personal/side projects because I know no one else would need to maintain the code.)

2

Like you, I think it's a bit paranoid. The rules for semicolon insertion are well defined in JavaScript, just as they are in Python and CoffeeScript. No one litters Python or CoffeeScript with semicolons, so why is JavaScript treated differently?

I think it's an overreaction to the wretched state of typical JavaScript code from about ten years ago—JavaScript was viewed as a weak, buggy, ugly, no-good language. It was an embarrassment. You couldn't possibly write good code in JavaScript!

Then, people came along and tried to prove that you could write beautiful, clear code in JavaScript. The "always use semicolons" rule was part of this wave. And to be honest, it can make a few situations a bit clearer.

Why is JavaScript still treated differently?

There's inertia. And it shouldn't be overlooked that people who appreciate explicitly structured code often prefer C-style languages. People who appreciate implicitly structured code often move on to non-C-style languages (like CoffeeScript).

1

I use them in Javascript strictly for consistency. If most lines have

Python has them for edge cases such as multiple statements on a single line, javascript has them and since you will find them regularly used I conform to the norm where they are used.

I cannot find a use for multiple statements on the same line and therefore do not foresee using semicolons.

1
  • Yes, I've fixed the Python example. But the point remains, Python also has semicolons, you are welcome to put them after every statement (and have to if you have more than one on each line) but people don't use them. Commented Aug 7, 2011 at 13:39
1

If you use something like bundle-fu, and asset manager for your web app in rails, then it would break horribly if it doesn't encounter a semicolon at the end of token in javascript. So It is a good practice to put one.

1
  • Well, the big three, YUI Compressor, Closure Compiler, and UglifyJS, all do semicolon insertion. I'm not surprised that the ruby port of JSMin has problems. Commented Aug 7, 2011 at 17:14
1

I can't remember which exact version of IE, but there are some cases where IE will literally error out if a semicolon is missing. IIRC it's when you have in the global scope something like:

var myFunc = function() {
  ...
}

If you don't add the ; after the closing brace, the program will actually fail on some versions of IE. That, along with the other reasons (including Crockford's recommendation to always use them explicitly) have led me to always use them explicitly in every case.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.