Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Why use semicolons to terminate statements in modern JavaScript or ActionScript?
13 points by timknauf on Nov 24, 2008 | hide | past | favorite | 39 comments
I hope the question doesn't come across as flamebait, because I'm genuinely interested in the response here. My background is mainly in the largely semicolon-less Python and Ruby. This may have impeded my understanding of the issues involved. :^)

ECMAScript-derived languages have inherited many syntactical conventions of C-style languages (e.g. braces to demarcate blocks). However, while semicolons are required to terminate a statement in C-style languages like Java, they are optional in modern variants of Javascript and Actionscript, where a line feed is considered to imply a semicolon if the statement on that line is complete.

Being able to leave out semicolons is blissful as far as I'm concerned. When coding in Java, I frequently run into compiler errors because I have neglected to type a semicolon, whereas I can't think of a single time when omitting semicolons in Javascript or Actionscript has caused me problems.

However, the code style of others (e.g. website Javascript, or Actionscript open source projects) suggests that my opinion mustn't be widely held; I see semicolons everywhere.

Now, Javascript on a web site has to run in many different browser environments, and I can understand how fear of incompatibility could keep coders locked to semicolons (although like I say, I haven't seen any browser problems myself). But Actionscript gets compiled, removing the uncertainty about how syntax will be interpreted on the client. So why are semicolons still being used now that they are optional in Actionscript 3.0? Do semicolons provide a secret benefit that I'm not aware of?




Two areas that I can come up with:

1. Minification -- If you want to minify your JS, you might run into problems if you don't insert all necessary semicolons.

2. Convention -- If you wrote js code with no semicolons and then showed it to other JS programmers, you'll get a funny look, a slap in the face, or a free copy of "Javascript for Dummies", depending on the context.


"1. Minification -- If you want to minify your JS, you might run into problems if you don't insert all necessary semicolons."

Only if the minifier is broken. Some of them are (I don't want to name names since it's been a while since I checked). The relevant advice would be "don't use broken minifiers," not "don't use automatic semicolon insertion."

"2. Convention -- If you wrote js code with no semicolons and then showed it to other JS programmers, you'll get a funny look, a slap in the face, or a free copy of "Javascript for Dummies", depending on the context."

The correct response to which is to politely refer them to ECMA-262 section 7.9 and go on your way.


The correct response to which is to politely refer them to ECMA-262 section 7.9 and go on your way.

I'll let you know how that goes. I even have a particular person in mind... :^D


Hmm, I hadn't considered the minification context - good point. That said, doesn't HTTP compression make minification largely unnecessary?

As for convention: yes, I have indeed had some funny looks when asking this question in real life (no slaps yet, though). If you're working in a team, you obviously need to conform to one coding style; I'm coming from a mostly sole-coder perspective. But why does the convention persist? (Is that a strange question to ask?) Is it simply the weight of tradition, or are there other benefits?


Doesn't HTTP compression make minification largely unnecessary?

It depends. If you have really high traffic or you care about every last microsecond of responsiveness, minification is essential. Also, minifiers these days tend to know about scope and program structure and may even be able to figure out when you're referring to defined browser objects like 'window'. So you just get that much more bang for the buck when combined with other forms of compression.

As for your other question, about convention: back in the dark days of the mid-90s Javascript was just the subset of scripts that both IE and Netscape would support. Omitting semicolons usually caused horrible bugs in one or the other. Also, most tools for formatting source code assume that newlines are not significant, and may wrap, split, or join lines in a way that breaks the logic.

Anyway, most battles over source code standards end in the most explicit option winning. This case is no exception.

Your question is fair, considering that ECMAscript is standardized now. In principle, you could switch to a newline-terminated style, thus saving a whole extra character per line. (But that would be eliminated if you minified).

However, even today, I would guess that omitting semicolons risks breakage. Browser makers don't test much with newline-terminated scripts.


Thanks for the considered response: this sort of background information is exactly what I was looking for.


Leaving out semicolons leads to errors. Ambiguity etc...

return

[1,2,3]

What should that do? Should it return, or return [1,2,3]? There are many other examples. Use semicolons and there is no debate over what should happen. Making them optional in javascript was a ridiculous idea.


I agree. You often get multi-line statements and in many languages/APIs they're a nature way of doing things. Here's an example (in no particular language):

   win = Window.new()
      .setTitle("A new window")
      .setForeground(Red)
      .setBackground(White)
      .setMenuBar(fileMenu, viewMenu, helpMenu);
I think this would be uglier and more error-prone if instead you had to use \ or some other character to indicate they are all part of the same expression:

   win = Window.new()\
      .setTitle("A new window")\
      .setForeground(Red)\
      .setBackground(White)\
      .setMenuBar(fileMenu, viewMenu, helpMenu);


Interesting. I hadn't come across that idiom before. In Python, you'll have things like:

  myLongList = [1, 2, 3,
                4, 5, 6,
                7, 8, 9]
No continuation character is needed, because the continuation is implied.

However, I can't think of a direct parallel to your example above. It looks handy. What API/language are you alluding to?

I guess the Pythonic way would be something like:

  win = Window(title = "A new window",
               foreground = "Red",
               background = "White",
               menuBar = [fileMenu, viewMenu, helpMenu])
But I disgress. :^)


JavaScript can just as easily attain this way of using named parameters:

  win = Window.new({title: "A new window",
                    foreground: Red,
                    background: White,
                    menuBar: [fileMenu, viewMenu, helpMenu]});


What API/language are you alluding to?

As i said before: no particular language.


The dot notation itself indicates continuation:

  win = new Window().
        setTitle("A new window").
        setForeground(Red).
        setBackground(White).
        setMenuBar(fileMenu, viewMenu, helpMenu);


Here's a more plausible example. Let's say you are trying to call one function out of a list of functions. What do you think this code does?

  function getIndex() {
    return 0  
  } 
  function f1() {
    alert("foo") 
  } 
  function f2() {
    alert("bar") 
  } 

  var intIndex = getIndex() 
  [f1, f2][intIndex]()

It looks like it should alert "foo", but run it and you get an "intIndex is undefined" error. Good luck debugging that!

The problem is, the javascript rules for continuing lines are that whenever the next character is any of [({+-, the line is assumed to continue. This is generally correct but not always. For comparison, the analogous Python rule is that a line continues either with an explicit \ or when one of [({ has not yet been closed with its pair. The Python rule doesn't lead to any ambiguous cases that I am aware of, because unclosed parentheses would just be invalid syntax.


Interesting. I've encountered errors in a similar vein, which in retrospect must have been caused by using an anonymous list in a similar way to your example:

  [f1, f2][intIndex]()
The 'solution' seems to be something like

  var functions = [f1, f2]
  functions[intIndex]()
but that's a big loss for conciseness.


The most convenient solution is just using a semicolon. If the line continuation rules were the Python ones, this would "just work"....


Keep in mind that I come from a mainly Python and Ruby background; both of those languages have always had newline-terminated statements. Yes, neither Python nor Ruby nor newline-terminated Javascript would return the desired result. But neither language seems to be suffering hugely as a result. (As far as I know.)

Why would you write a return statement like that in the first place? (Not intended as flamebait - I am genuinely curious to know.) If it is a simple typo that separates the 'return' from the '[1,2,3]', then isn't the negligent typist just as likely to leave off the all-important semicolon? Or is there a genuine reason you might want to put the [1,2,3] on a line by itself?


JavaScript syntax lets you write statements over multiple lines - if the first line cannot be parsed correctly it assumes you meant to continue over to the second line. This leads to odd error messages and JavaScript being harder to debug without semicolons.

Note that this is different to, say, Python, where newline explicitly indicates termination of a statement.


Well, Python will let certain statements continue over multiple lines as well, e.g.

  someFunction(parameterOne,
               parameterTwo)
I think maybe the difference is that Python has always treated newlines the way it does now. JavaScript, on the other hand, has developed idioms based on the semicolon model. So has the rug has been snatched out from underneith its users by suddenly making them optional? Does the change make a lot of useful idioms harder to implement?


ok here's a more usual situation in which the programmer is blindly using their favorite bracketing style, and come across the issue...

function getObject()

{

    return       // returns undefined, not the object.

    {

        age: 30,

        name: "axod"

    }
}

Personally I hate that style of bracketing, but some swear by it.


Yeah, not really my favourite bracketing style either. Good example though - it is conceivable that this could happen.


Making them optional in javascript was a ridiculous idea.

But since they are optional now, using them throughout our code won't help us for the example above: it would still wrongly return undefined because of the implied statement end. So it could be argued that semicolons provide a false sense of security in this new, semicolon-optional world. :^)


Okay, putting all talk of practicality (interpreters, minifiers, convention) aside, let's look at the language itself for a bit; this could lead to some interesting discussion.

JavaScript has two ways of designating the end of a statement. Here is (1):

  ;\n
And here is (2):

  \n
Now, the semicolon can't help you if you type:

  return\n
  {a:1\n
   b:2};\n
because statement end (2) has already kicked in, and so the code will return undefined.

So, given that statement end (2) is part of the standard (and doesn't look like leaving it anytime soon), is there any language reason to use statement end (1)? Is it purely a visual signifier? If so, is that useful to a majority of coders? Am I in a minority for considering it visual noise? Remember, we're putting aside practicalities like existing conventions, minifier capabilities and browser implementations for the sake of the exercise.


Minification has already been mentioned, but I wanted to re-iterate as it's such an important point. You can reduce size over the wire by as much as 30-80% by minifying and obfuscating (something like YUI or Dojo compressors do this).

Not having semi-colons risks a lot of code breakage. Doug Crockford's JSMin has an aggressive mode which always strips line breaks and another which doesn't to avoid breakage when semicolons don't exist.

Personally I would just say that if you don't use semi-colons you should think hard about why you code at all. I'm not the anal-retentive type but sloppy code isn't awesome. I would put this in the same category as naming variables $whatever or $x. If you've never picked up someones second hand project you may not appreciate why a pleasant coding style matters.


I wasn't intending to come across as being anti-code-conventions! I love coding and I'm a bit shocked that my questions suggest to you that I might have a sloppy coding style in general. :^) I agree that conventions and shared idioms are extremely important. My question is, "why is this a convention?", not "why should we use conventions at all?".

I'm all for adopting the semicolon convention myself, even in sole-programmer projects, if there are reasons for using it; that's basically why I asked the question in the first place. (And of course I adopt it if contributing to a project which already uses it - no need to rock the boat.) Things like minification are exactly what I'm interested in, although I was under the impression that HTTP compression does a better job than Javascript minifiers at solving the size problem. Obfuscation is, of course, another matter entirely.


Welcome to the real world, where "the next programmer to work on this might be dumber than you" is considered a valid justification for cargo-cult programming.

A good minifier should replace line-breaks with semicolons as appropriate using all the same inferencing rules as JavaScript itself. Until one of those comes along it seems like using semicolons is necessary to make the best use of the tools that do exist.


Welcome to the real world, where "the next programmer to work on this might be dumber than you" is considered a valid justification for cargo-cult programming.

Yes, I am a little surprised that some of the responses have assumed that because I'm questioning the usefulness of a syntactic element, I'm not interested in code quality or consistency. Quite the reverse: I'm very interested in producing code that is as clean as possible. What I've been trying to discover is whether the semicolon is a vestigial element that can now be left behind.

But the concensus seems to be that there is still a present need for semicolons, at least when it comes to interpreted JavaScript (though I'm still not convinced that the same holds for always-compiled variants like ActionScript). And like you say, current tools expect - quite reasonably - a certain coding style, even if they should use the full set of inferencing rules.


I've written JavaScript sans semicolons for years and have not encountered incorrect parsing by any browser. I find this style cleaner and easier on the eyes.

I haven't done any testing regarding parsing speed, but I would be shocked if anyone can demonstrate a measurable speed difference in a realistic testing scenario.


I've written JavaScript sans semicolons for years and have not encountered incorrect parsing by any browser.

Yes, neither have I - but then I'm doing fairly simple stuff. I do test across a fairly broad range of browsers, though.

I find this style cleaner and easier on the eyes.

I'm glad I've found at least one kindred spirit in this regard! I was beginning to think I was the only one.

I haven't done any testing regarding parsing speed, but I would be shocked if anyone can demonstrate a measurable speed difference in a realistic testing scenario.

Perhaps with very, very large and complex code if the JavaScript engine uses an old-style interpreter? But surely the problem will continue to diminish away to nothing as more JavaScript engines implement efficient compilation.


I'm glad I've found at least one kindred spirit in this regard! I was beginning to think I was the only one.

People with a background in non-brace-and-semicolon languages are more likely to feel the same way. Others (e.g. recent graduates learning only Java) may be less comfortable with the lack of semicolons, and may regard it as "sloppy," perhaps from a lack of familiarity, or because they've never thought about it or haven't read the specs and are simply regurgitating what they've heard.

On a related note, in CSS the semicolon is a separator, not a terminator, so to pick on some CSS from an arbitrary Web page:

    body  { font-family:Verdana; font-size:10pt; color:#828282; } /* unnecessary semicolon */
    body  { font-family:Verdana; font-size:10pt; color:#828282 } /* equivalent but shorter */
Also on the topic of cargo-cult coding cruft, you'll often see pseudo-XHTML with self-closing tags that include a space, e.g. "<br />", invariably served as text/html, where it is equivalent to "<br>" with the addition of two extraneous characters and one syntax error. People still actively recommend this practice, despite the fact that even when served as HTML, the extra space has not been necessary since the days of Netscape Navigator 3 or 4.

Perhaps with very, very large and complex code if the JavaScript engine uses an old-style interpreter?

JavaScript is only parsed once, even in ancient browsers, and no matter how much code there is, the time required to download it, not to mention executing it, will typically be orders of magnitude greater than the time spent parsing it. I had never heard the performance reason before as a justification for this practice, but I consider it a total red herring until someone provides hard numbers that suggest otherwise.

Ultimately this is a question of style and personal preference, but if you happen to prefer the cleaner style as I do, I see no technical reasons why you should not use it.

Finally, never forget Wadler's Law:

http://www.haskell.org/haskellwiki/Wadlers_Law


Thanks for the detailed reply.

People with a background in non-brace-and-semicolon languages are more likely to feel the same way.

Yes, and most of them are off happily working with their Pythons, Rubys, Haskells and the like, staying well away from this sort of discussion. :^) I've been writing a lot of ActionScript lately (making games which target Flash), so I've been thinking about ECMAScript-style syntax a lot more than I have in the past.

Also on the topic of cargo-cult coding cruft...

I see "cargo-cult coding cruft" most often in languages which are parsed by a client (e.g. CSS, XHTML, JavaScript). I suspect that this is due to fear that some client, somewhere will choke on the actually-correct code. And whaddaya know - sometimes that client actually exists. It's called Internet Explorer 6. ;^)

Finally, never forget Wadler's Law

Yeah, I'm reminded of an old Python joke:

  Question: Why is Python such a productive language?
  Answer: You won't have to spend any time arguing about brace style.


A domain-specific compression algorithm will often outperform a general purpose compression algorithm, and sometimes a combination of both is even better.

Besides, downloading a zip file is still faster than downloading the uncompressed file, so either everybody's doing HTTP compression wrong or it's not so hot to start with.


Explicit statement termination is all about speed - ensuring that JavaScript interpretation is as rapid as possible. Terminating a statement implicitly requires additional processor cycles - and we still need to husband those cycles to maintain a responsive user experience.


Hmm, interesting point. I've never worked on a truly large JavaScript codebase; it would be interesting to test the effect of implicit and explicit termination on various JavaScript engines. Presumably the performance penalty would apply to traditional interpreter-style engines much more than to modern compiling engines like V8.


Explicit statement termination is all about speed - ensuring that JavaScript interpretation is as rapid as possible.

Is this correct? I would imagine that JavaScript implementations typically compile it into intermediate code, wihch is then interpreted. If so, then it shouldn't make any difference whether you add the semicolon or not.


Thanks for the responses, everyone! Sounds like - regardless of what I might think of semicolons personally - the reality of the current crop of minifiers and JavaScript engines makes a case for their continued use.

Now, how about ActionScript? This has a compilation step, so the Flash VM is not dealing with your code directly. If we discount ActionScript obfuscators, could a stronger case be made for omitting semicolons there?


I highly recommend you use JSlint to pick up on things such as forgotten semi-colons to improve the quality of your code.


they allow copy/paste with other C syntaxish languages

edit: Sorry, I forgot to include caps, and full stops for that first sentance.


Hah, do I detect a little light jab in your lack of punctuation?

I guess it partly depends on how you view the relationship between programming languages like Javascript and the typographical conventions of natural languages like English.

I tend to think of a series of statements in a programming language as more akin to a to-do list of imperatives than a paragraph from a recipe book. If you are writing a to-do list, you don't need to mark the end of the instruction; the end of the line functions for this purpose. Something like this would be sufficient for understanding:

  break eggs into pan
  fry the eggs
  remove the eggs from pan
  eat the eggs
As opposed to the recipe approach:

  Break the eggs in the pan; now fry the eggs; next remove the eggs from the pan; now eat the eggs.
More syntactical marks are required for clarity (including many semicolons!), but the first approach (the to-do list) is arguably closer to how code is actually written.


or in Factor or Forth:

: pan egg break-in fry remove eat ;




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: