Beware of JavaScript semicolon insertion

One of most tricky behaviors by JavaScript interpreters is semicolon insertion.

Why semicolon insertion?

Unfortunately, semicolons are optional in JavaScript, which leads to developers being sloppy, using them in some places, while omitting them elsewhere. “Luckily”, JavaScript interpreters take this into account, and at runtime, insert semicolons where it thinks it should be one.

Good and bad code style examples

So, how is this a problem? Let’s start by taking a look at the below code:

// Good
return {
	javascript : "fantastic"
};
// Bad!
return
{
	javascript : "fantastic"
};

The problem

So, I’m sure some of you wonder what the hell’s wrong with having the opening curly bracket on a new line? You love that coding style and it all becomes clearer. The answer is semicolon insertion. The bad code is interpreted like this:

return; // Semicolon inserted, believing the statement has finished. Returns undefined
{ // Considered to be an anonymous block, doing nothing
	javascript : "fantastic"
};// Semicolon interpreted as an empty dummy line and moved down

My advice

Since it does matter where you put the curly brackets, my strong recommendation is to use the opening one at the end of the line, preceded by other code. Also, make sure to always put semicolons in your code, to avoid potential problems.

Acknowledgements

I first saw this lovely example being presented by Douglas Crockford at @media Ajax 2007 (my report), and my pal Remy presented it in his blog. I just wanted to re-iterate the point here, since a lot of people doesn’t seem to know about semicolon insertion.

35 Comments

  • Remy Sharp says:

    For anyone interested in the impact of running this code – here's a working demo of why you should format your code properly: http://jsbin.com/azufi

  • For those that use Textmate, there is actually a little bundle, that goes a long way.

    It’s called JavaScript Tools, was originally written by Andrew Dupont, and has since been adopted and moved to bundleforge.

    http://bundleforge.com/

    For me, the most interesting feature of the bundle is that it runs your javascript through jsLint every time you save the files.

    That will give you immediate feedback on bad coding style, missing semicolons, etc.

  • Robert Nyman says:

    Jonathan,

    Yes, I know that you prefer that style (I don’t). 🙂

    But also, there are JavaScript approaches, such as the Yahoo Javascript Module Pattern, which relies on returning an object.

    Besides, someone like you know the ins and outs of JavaScript, so you when things will break and when not. My take is that most people don’t, so personally, I’d recommend using the opening curly bracket on the same line as the code.

    Morgan,

    Well, maybe. JSLint is very good overall, but it might complain about something which you’d deliberately want that way, and it feels a bit counter-effective to demand JSLint validation in those cases.

  • Robert,

    It is possible to pass options to the lint, to tell it what to bitch about, and what not… but I do see your point, and some of the “complaints” might not be obvious for the less experienced JavaScript programmer… and this will just increase frustration without necessarily increasing quality of code.

    But then again, I hate warnings (or broken windows) as much as the next developer, so if I am Lead, you’re just going to have to deal with the harsh rules 🙂

  • icaaq says:

    That and other things is noticed when you slap your code into lint http://jslint.com/

  • Robert Nyman says:

    Remy,

    Great, thanks! 🙂

    Morgan,

    Thanks for the tip! Personally, I use that bundle in TextMate, and it sure saves me some problems at least.

    icaaq,

    Absolutely!

  • Andrew Noyes says:

    Great tip on the TextMate bundle, Morgan. I wish Panic would implement something similar into Coda. Maybe we can hope for something good in MacRabbit Espresso?

    Robert, you might consider JavaScript Lint in favor of JSLint. I used to whole heartedly stand by JSLint, but more and more it seemed like Douglas Crockford either making a point or being strict beyond the point of practicality. For example, in for loop declarations, JSLint will throw an error for using the increment operator. Crockford has a valid reason for this: it’s hard to read code like i + --i, and without the spaces this would cause problems. However, even when you’re just incrementing your loop variable, if you use the normal settings on JSLint, it will throw an error for using i++. JavaScript Lint is a bit more sensible about this in that the increment operator is valid so long as you’re not combining it with other operators.

  • Personally, I avoid returning object declarations. If a function is meant to return data, I'd rather set it to a variable and then return the variable. This ensures that the return statement is the last line of the function, aiding overall readability.

  • Just last week I created a pre-commit hook for SVN, that prevents me from commiting .js files with "console." in them.

    Perhaps I should just expand that to run my stuff through jsLint as well.

  • Steven Clark says:

    Interesting, as I've always tended to find curly braces on the new line more readable (maybe it's just me). It's something instilled in programming 101 classes. But with JavaScript I'll have to curb that practice, I guess.

    Thanks.

  • Steven,

    It's actually quite an interesting debate on placement of curly braces.

    On one hand, it does seem to improve readability for nested statements, but on the other hand it also increases the amount of "blank" lines in your code. This secondary effect means that you will be able to see less of your code on the screen at any given moment, which means a whole lot more scrolling.

    I know that Microsoft advocates "opening brace on new line" for C#, which might give the impression that it is common or even considered good practice. I am sure that there are other vendors that also advocate this practice, so for once I am not bashing MS 😉

    But, once you get comfortable with a language, you should be able to read indented statements easily, regardless of placement of braces, and the value of using newlines for opening braces is greatly diminished. For JavaScript it can be fatal, and I expect that other languages like ActionScript would suffer the same fate.

    It is my experience that you get the better code quality by assuming some level of skill by the reader, rather than writing code that is readable to newcomers of the particular language… they'll get the hang of it soon anyway.

  • Robert Nyman says:

    Morgan,

    Yeah, with proper options specified, I think I can support that initiative then. 🙂

    Andrew,

    Yes, I know about it, but at the end, it's just about what options to specify. Meaning, I use the increment approach and JSLint, and we get along fine.

    Thanks for the tip, though!

    Steven,

    Well, you don't have to, if you're careful. But personally, I'd just recommend it.

  • […] Others have pointed out this problem, such as in the JavaScript Style – why it’s important and Beware Of JavaScript Semicolon Insertion articles, both of which give similar examples. Another example of the problematic nature of […]

  • […] Esiste anche un altro problema molto più subdolo generato dal “semicolo insertion”, ma per la cui analisi vi rimando a questo articoletto. […]

  • […] Beware of JavaScript semicolon insertion – Robert’s talk […]

  • Freddie Mack says:

    I like braces on separate lines, delineates blocks of code very clearly. As for semicolons, I come from a C background and get very nervous when statements don't end in one. I don't like to let interpreters and compilers make decisions I should be making.

    Similarly, I simply smile when folks get tense about the absence of braces in code snippets like this:

    if (condition)

    one line of code;

    else

    other line of code;

    sitting all by itself with one line of white space above and below.

    You folks have fun arguing about braces and semicolons, I've got some code to write.

    Freddie Mack

    dopey box loses indents – I leave them to you

  • Robert Nyman says:

    Freddie,

    Given the enormous research and tests done on a vast amount of developers, the result has been that two of the most common roots of problems are omitting semi-colons, and not using braces for one-line if statements.

    You can do whatever you want, but out of responsibility to the people paying for your code, and for the developers that will take over it, I think it's a good idea to pay heed to the advice in various linting tools.

  • My first expression was what the…!!!

    Thanks a ton for your post. I was going to write a JS coding guidelines document. I am a guy who always puts curly braces in new line and would return something very complex in just one return statement. I liked the Jonathan Snook's way of returning something. 🙂 Thanks again.

  • Robert Nyman says:

    Kumar,

    Glad it inspired you!

  • rtpHarry says:

    I'm not an expert on the details of JavaScript but I just wanted to ask out of curiosity – am I to presume that this code would not run?

    <code>

    return; {

    javascript : "fantastic"

    };

    </code>

  • Robert Nyman says:

    rtpHarry,

    Try it and you will see. 🙂

    Technically, all of the code runs, but the returned value will be undefined and the block with the curly braces will just be overlooked.

  • rtpHarry says:

    so it seems the code runs the same if you put it on a new line or not. are you saying that it is harder to spot of you put your curly braces on a new line?

  • Robert Nyman says:

    rtpHarry,

    No, it doesn't run the same. If you have/get the semicolon inserted right after return, as I stated above, it returns undefined and not the expected JavaScript object. What I mean with that it runs, is that it is being evaluated by the JavaScript interpreter but the value isn't returned.

    Just try out the variations yourself and you will see.

  • rtpHarry says:

    oh I understand you now. You are talking about the compiler automatically inserting the semicolon not somebody maliciously slipping one in there to see if you noticed 🙂

    so this problem only crops up with return { };?

    do I also have to watch it with something like

    <code>

    $(document).ready(function()

    {

    // some callback code

    });

    </code>

  • Robert Nyman says:

    rtpHarry,

    Yes, the compiler does it. Mainly for return statements, but you would want to ensure a consistent coding style.

  • Anthony Garrett says:

    Unfortunately, while breaking the line after the curly bracket makes good sense for the reasons you gave, it is also very bad general programming practice that is almost universal in programmers brought up in the object programming paradigm.

    Long-standing general principles say that bracketing should be aligned for code readability. Failure to match brackets in complex code makes it almost totally unreadable. So, as far as I am concerned, the best approach is to match brackets and avoid code that produces problems when a semicolon is inserted.

    Personally I work to readability standards where brackets around multi-line code is matched but when brackets are around simple code that fits on one line then I don't split it – your example would be just:

    return {javascript:"fantastic"};

    On the subject of JSLint – it seems odd that it marks: function {…some code…}; as having an unnecessary semicolon – it's a statement, it ends in a semicolon (I haven't tried all possible settings but none obviously turns this off). If you write your code without semicolons on functions, you're asking for trouble when someone strips out the new lines to compress it.

  • biziclop says:

    Once I wrote a similar code:

    var someFunction = function(){ dosomething; }
    // comments, missing ; at the end of previous line
    (function(){ closure contents; for extra fun, return a function here; })();

    I had some great WTF moments 🙂

  • […] There was a programme on TV once and they showed all these x-rays with weird things in like toy cars and bottles and stuff, and … oh yeah, semicolon insertion. That’s where the JavaScript interpreter makes it easier for non-programmers to write JavaScript that works and makes it harder for programmers to write JavaScript that’s correct. Silly. Here’s what happens: […]

  • Drak says:

    Seems a bit of a shout out about nothing. I’ve been Javascripting for about 14 years now, and I’ve never had this problem.. ever. And I use curly braces on a new line.

    Except where I’m making an object. And anyway, imho, using a return statement you should ALWAYS starts whatever you return on the same line, otherwise you’re making your code obscure.

  • […] (???? Return braces pitfall ???? Semicolon insertion ?? JavaScript ???????) ??????? (??????????) […]

  • […] Beware of JavaScript semicolon insertion – Robert's talkOct 16, 2008 … One of most tricky behaviors by JavaScript interpreters is semicolon insertion. Why semicolon insertion? Unfortunately, semicolons are optional …robertnyman.com/…/beware-of-javascript-semicolon-insertion/ […]

  • […] have read this article, where an example is shown. Please explain why the code snippets below return different results due […]

  • […] have read this article, where an example is shown. Please explain why the code snippets below return different results due […]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.