Semicolon in JavaScript

2019-08-01

CASSIUS Did Cicero say anything?

CASCA Yes, he said something in Greek.

CASSIUS What did he say?

CASCA If I told you I understood Greek, I'd be lying. But those who understood him smiled at one another and shook their heads. As for myself, it was Greek to me.

from Act 1, scene 2, Julius Caesar (1599) by Shakespeare

What we cannot understand appears as Greek to us. We all recognize this experience, but from different contexts.

When we have reason to believe something is not gibberish (by i.e. recognizing the letters as Greek), we presume the words are parts of a valid expression. We know that someone who knows Greek would have no trouble understanding the words. If s/he would interpret the meaning of the expression as it was intended is altogether another question.

In natural languages, it's possible to be guilty of obscurantism, deliberate attempts at distorting the truth. This is not possible in formal languages from the parser's point of view, but it is possible from a human perspective.

An expression has one (and only one) meaning in the context of the grammar, but with that said it might not be the case that the application does what the developer intended it to do. However, the application does exactly what the code intends to do.

The compiler follows instructions, it doesn't interpret semantics in the same way as we do. Therefore the notion of obscure code, provided that the application executes, is something subjective, a potential conflict between what the application is told to do by the code and what the developer predicts it to do from his or her understanding of it.

Using semicolons is about exercising good taste by avoiding border cases and unnecessary complexity.1 There's no such thing as information overload, only bad design. ― Edward Tufte

People have strong opinions about semicolons. I usually avoid discussing this topic because other topics interest me more. In the end, I believe consistency to be more important than whether you make use of semicolons or not. However, at the same time, we should note that consistency is often impossible when not using semicolons.

Something I often hear from enemies of semicolons in JavaScript, is that it doesn't matter if we use them or not. This is not true, or at least not always true. Someone who claims that semicolons don't matter is either ignorant of Automatic Semicolon Insertion (ASI) or an involuntary obscurantist.

There are countermeasures (proper settings in for instance ESLint or JSHint) that would warn us when ASI is a problem. But even then, we can't be sure the chain doesn't break at some point. Errors could arise when we use Babel.js, a minifier, or any other technology that performs analysis of source code and build an Abstract Syntax Tree (AST).

A compiler can't read our minds, and ASI is set up to decide for us since JavaScript occasionally does need semicolons. JavaScript uses a compiler to interpret our code, but it is not a compiled language. Every time a parser deals with our code there is a small chance it will break due to the absence of semicolons, since the JavaScript parser uses semicolons as a delimiter. Clever linting can only warn us about when we most likely would want to use semicolons. It is true that often semicolons don't matter since the ASI will only in border cases interpret our code erroneously in relation to our intentions.

There's a difference between ending up with obscure code that we don't quite understand and choices we make that make the code obscure by design. Only if we wouldn't use Babel.js, no minifiers and knew all the rules of ASI by heart there would be real arguments for not using semicolons. Why carry the cognitive extra load for the sake of semicolons?

At Stackoverflow, Reddit and Hacker News there are lots of examples of cases where the absence of semicolons in JavaScript makes the code break. This example is from Stackoverflow.

var fn = function () {
  //...
} // semicolon missing at this line

// then execute some code inside a closure
(function () {
  //...
})();

According to the author of the post, the compiler would after the ASI process translate the code like this.

var fn = function () {
  //...
}(function () {
  //...
})();

Uncertainty is something we want to remove, whenever possible. The information overload a semicolon implies is not very large. On the other hand, if problems arise when not using semicolons we should think it's bad design - because it's not something supposed to ever happen.

By not using semicolons we end up in a situation where our tools might fail, without proper settings. If we say use a good minifier and have semicolons, the minifier thinks for us. But if we don't have semicolons it doesn't matter how good our minifier is, errors can still emerge, unless with make use of other tools that warns of ASI hazards. Are we absolutely sure our tools are correctly set up? Are we advanced enough to know all the details of AST, ASI and other important topics we need? If yes, we will have the occasional semicolon injected anyway. And if our aim is consistency, why now always use semicolons?

We avoid ambiguity and obscurity in the eyes of the parser by the use of semicolons. This is why TC39 speaks about 'ASI hazards'. Even though I don't like the idea of a language feature that need external tools to work properly, I think we should be allowed not to use semicolons. Why break the Web? The reason why the TC39 committee are still discussing 'ASI hazards' in the first place is,

it's a recognition by the committee that the no-semi style is likely to become more hazardous over time, and that the best way to avoid said hazards is to… use semicolons.

If we know the tools we are using it's possible to avoid the hazards, for the time being. But how about tomorrow? If we programmers are lazy, isn't it more convenient for us not bothering about a problem and accept a solution that comes in a handy one character box.

The JavaScript parser will keep using a semicolon as a delimiter (removing that would require a new language). We know that. If there is a solution (the use of semicolons) that creates the possibility of never having to think about semicolons, how parsers and different tools handle them and so on, why choose to make our applications vulnerable to problems - now and tomorrow? Again, by using semicolons in our code we avoid any such problem. We create cognitive space for dealing with other hazards. As Occam would have it,

[t]he simplest solution is most likely the right one.

About | Archive