
Semicolons matter - josep2
http://blog.rrowland.com/2016/04/11/semicolons-do-matter/
======
bilalq
It still surprises me that this discussion pops up so often. Even more
surprising is that people assume as a matter of fact that forgetting to put a
semi-colon is the problem.

> When your code’s intention is ambiguous, your JavaScript engine will attempt
> to fill in the gaps.

This is kind of misleading. The JS engine isn't making some guess. There are
clearly defined semantics on how ASI (automatic semi-colon insertion)
operates. Let's put aside whether ASI is good or bad-it's just part of
JavaScript. Ending all your lines with semi-colons won't save you, only
understanding ASI will do that.

Take this example:

    
    
        function foo() {
          return 
            'A really long string that I've put on another line';
        }
        console.log(foo());
    

You'll see that `foo` returned undefined here. Why? Because ASI terminated
`return\n` as a statement.

Isaac Schlueter wrote a post on this years ago that pretty much says
everything I'd want to say on this topic:
[http://blog.izs.me/post/2353458699/an-open-letter-to-
javascr...](http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-
leaders-regarding)

~~~
dugword
> Ending all your lines with semi-colons won't save you, only understanding
> ASI will do that.

It will save you if you use JSLint/JSHint/ESLint/etc.

In your example you will get an error about a semicolon missing after the
return statement.

If your convention is to always use semicolons your editor can let you know
you have made a mistake. If you don't use semicolons then you have to turn off
these warnings from your Linter and you won't catch the error until you see
weird results at runtime.

And that's the purposing of always using semicolons, so you can have automated
tools help you.

~~~
bilalq
Sure, a linter can handle that situation. But linters can handle the
semicolon-free style just as well[1]. There is no real value-add from
semicolons; they're just a matter of stylistic preference.

[1]: [https://github.com/feross/standard](https://github.com/feross/standard)

------
ArmandGrillet
Non-ambiguous titles also matter, in this case it should be "Semicolons matter
in JavaScript". Too many links have this problem and it makes it difficult to
find an article when searching for something on HN.

~~~
ChrisGranger
Agreed. Even though Hacker News obviously leans towards articles about
programming and such, I was half-hoping this was an article about grammar.

~~~
rrowland
Good idea for my next topic. ;)

For the record, I didn't post my article here, but if I had I would have
specified the language.

------
jack9
His example has at least 2 missing semicolons.

function Logger() { }

// Log something to the console at a specified level

Logger.prototype.log = function(level) {

    
    
      console[level || 'log'].apply(console,[].slice.apply(arguments, 1));
    

}; // here

// Sugar functions for Logger.log

['info', 'warn', 'error'].forEach(function(level) {

    
    
      Logger.prototype[level] = function () {
    
        return this.log.apply(this, [level].concat(Array.from(arguments)));
    
      }; // here
    

});

~~~
draw_down
And yet, not only does it still function as it should without those missing
semicolons, the author didn't notice them missing. Hmm. Hmmmmm.

~~~
0942v8653
Not sure what you're trying to insinuate, but the first "// here" is the one
that broke the code as mentioned in the article.

------
epmatsw
Seems like everyone should just be using an automated tool to catch
missing/extra semicolons. No reason not to at this point, and eslint even
autofixes them for you.

~~~
taylorwc
That was my exact reaction too--I wonder how many people who spend any
meaningful amount of time in javascript do so without a good linter.

~~~
hyperpape
Outside of work, I spent a month or two writing little demos for my kids in
javascript using notepad. My old computer had died and I was borrowing one.
This was in ~2014 maybe?

------
bantunes
"Error establishing a database connection" \- caching matters.

~~~
rrowland
My baby DigitalOcean droplet was not prepared for HN traffic.

------
IshKebab
Kind of insane that this still hasn't been fixed. You should be able to put
something like `strict_semicolons;` at the start of a JS file to tell the
interpreter to _require_ semicolons for that file.

------
msie
Flame-on: I wish I could blacklist other people's code that don't use
semicolons. Perhaps that flagging should be put into a linter. That linter
will then update a global list of semicolon-optional code. Flame-off.

------
k__
Semicolons cannot save you: [https://www.youtube.com/watch?v=Qlr-
FGbhKaI](https://www.youtube.com/watch?v=Qlr-FGbhKaI)

Gist: Adding semicolons won't help, because you still have to know how
JavaScript inserts them automatically to add them in the right places.

~~~
__david__
Correct me if I'm wrong, but the only case you have to worry about is having
"return" on the same line as the thing you want to return. And you have that
problem whether or not you use semicolons in the rest of your code.

~~~
k__
The blog post mentions, that starting a line with [ or ( can be dangerous too.

But till hat example I didn't even know why this would make sense in the first
place.

I only use excessive parenthesis for math and store arrays, like the example,
in constants that describe their purpose, so I guess I dodged a bullet there
:)

------
bluedino
>> Be unambiguous with your code. If you’re ending a statement, use a
semicolon.

We're still going over this? _Javascript, The Good Parts_ came out close to 10
years ago and went over this.

~~~
gpvos
The problem here is that the assignment to Logger.prototype.log superficially
looks like a function definition, not like an assignment statement, especially
when you don't look too hard at the beginning.

------
adrusi
Honestly when you already have to keep track of JavaScript's other gotchas,
having to remember to look for likes that start with ( or [ and precede then
with a semicolon is not that much to ask. It seems silly anyway, but not
particularly damaging.

------
58028641
I never used semicolons and I have never had a problem. Just avoid ambiguous
code.

~~~
Cthulhu_
I have a short anecdote where not using semicolons caused problems. Or well,
not even in our code.

We were using (IIRC) a version of underscore.js that did not use or did not
end the final line thing (probably one of them self-executing functions) with
a semicolon. Because of reasons, our application would break in production
builds; the lack of semicolons would, in some cases, cause an issue after
concatenating that file with another vendor's file. A very obscure and hard to
track one, too - it took us weeks if not months to find it.

~~~
gpvos
I've seen recommendations to _start_ an included Javascript file with a
semicolon to avoid this problem.

~~~
fengb
Just concat using a semicolon instead of just a new line.

------
aerovistae
Can someone explain what's happening here? I'm a JavaScript dev, perfectly
familiar with JS and with semi-colon insertion, but I'm not following the code
after "This is how V8 sees it:"

I don't see how or why the two lengthy statements using `apply` are being
omitted entirely. I also don't see how that's "perfectly valid code" . . . I
tried running it and got an error 'cannot read property forEach of undefined.'

~~~
thiht
To quote the article: "I’ve removed the internals for clarity"

The content of the functions is just not relevant to the point he's trying to
make

~~~
aerovistae
Oh. I read over that. Thanks.

------
encoderer
Isn't it as simple as: You only need a semi colon if the next line starts with
"[" or "(" ?

~~~
acdha
The idea is that leaving out a semicolon saves an almost imperceptible amount
of time but requires you to be deeply familiar with the rules of every
JavaScript engine, any minifiers/transpilers/etc. which will ever see that
code, etc. and also commits you to rigourously applying that logic to every
future change.

That's where I'd expect this to come up most frequently – someone writes code,
tests it, it works and they move on but later someone makes a change and
doesn't notice that the original author left a trap for them. It's easy to
avoid that in the “ASI is cool” examples but real programs evolve over time
and you never want to make maintenance programming harder.

~~~
encoderer
If you're writing idiomatic modern javascript you're using modules -- we no
longer have the issue of two JS files being concatenated together in a shared
lexical scope. The only rules you need to be familiar with are the 2 I
mentioned. In my work, I've never thought about it as "imperceptible" time
savings: I worked on a codebase without semi-colons, and then didn't want to
go back. It was easier code to work with and write, and the feared downsides
never materialized.

I still use them to conform with existing code bases or linters that require
them, of course, but given the preference..

~~~
acdha
> It was easier code to work with and write

This is the part I'm still having trouble with – hitting ";" at the end of a
statement is harder than having to look at the next line and reason about it?
I mean, we're talking about a single character on the home row of most
keyboards – just how fast are you cranking out code?

EDIT: just to be clear, I don't see this as a huge factor either way – a
formatter can easily add or remove to your preference – so I surprised by the
way ASI proponents talk about it as a big deal. To me it seems like a minor
aesthetic preference on the level of “2 spaces or 4?” which doesn't
meaningfully change the way you're writing code and is significantly outshone
by something like switching to ES6, etc.

~~~
encoderer
I never have to "look at the next line and reason about it" \-- you simply do
not find yourself in a position very often of starting a line with an open
brace. I'm not going to list all of the little reasons why I found it more
enjoyable and easier to omit the semicolons. If you're interested, try it on a
project yourself. Suffice to say, I found several cases where my life was just
easier. Here's just one, from the very top of a file. It's easier to add
another import to this list:

    
    
      let states    = require('../data/states.json')
        , cloneDeep = require('lodash/cloneDeep')

~~~
acdha
Again, I have tried this and fail to see any more benefit than, say, changing
the indent size in my editor. Personally, I prefer

    
    
      let states    = require('../data/states.json'),
          cloneDeep = require('lodash/cloneDeep');
    

to

    
    
      let states    = require('../data/states.json')
        , cloneDeep = require('lodash/cloneDeep')
    

but that's an unimportant aesthetic preference. The structure of the code is
the same and my experience working with it is fundamentally unchanged. In
either case we're talking about a fraction of a percentage of the time it
takes to understand what the application is or should be doing.

Now compare that to something which actually matters: arrow functions,
classes, modules and imports, the newer data structures, generators, etc. In
that case, the time spent adopting a new style actually changes the structure
of the code you're writing and, hopefully, makes it easier to clearly convey
your intention to the next person who works on it.

~~~
encoderer
You have strong opinions about this. That's cool, and if you believe one way
is more correct that's also cool. My advice to everybody is the same advice I
gave you: try it. Try project without them and see. The only risk is that you
might find out you're wrong. If you want to add them later there are tools for
that.

~~~
acdha
> You have strong opinions about this.

It's odd that you appear to have ready my comments but missed the point where
I repeatedly said that I do not have a strong opinion about this and was
expressing my surprise that some people do.

------
degif
Google cache version - [http://goo.gl/x6jLVW](http://goo.gl/x6jLVW)

------
Animats
The trend towards optional semicolons isn't good. Javascript, Go, and Rust all
have different semicolon syntax and semantics.

~~~
nvader
The essential difference between Javascript and Go is that in Go, the
semicolons are inserted by the lexer[0], while in JS, they're inserted by the
parser. I don't know how Rust does it.

This means that Go's semicolon insertion rules are really simple: to judge if
a statement will end in a semicolon, you only need to examine that line
(actually, the last token of that line).

In Javascript, on the other hand, the start of the next line needs to be
considered as well. If the two lines could possibly be interpreted as one
statement together, then they are (except for restricted productions). [ and (
are common offenders that cause lines to "pick up" other lines, but unary +
and - can also be candidates when they get promoted to binary operators.

[0]
[https://golang.org/doc/effective_go.html#semicolons](https://golang.org/doc/effective_go.html#semicolons)

~~~
steveklabnik
Rust doesn't do any special insertion/deletion, but take an expression and add
a ; and it becomes a statement.

------
z3t4
Whether you are writing semicolons or not. Don't start a new line with (, [,
/, +, ++, or --. And never have a line break after return, break or continue.

------
lacker
I would prefer finding a subset of JavaScript in which omitting semicolons is
okay. Maybe this could be enforced in a linter. For example, if you never
begin statements with [ or (, would it be okay to omit all semicolons?

A semicolon doesn't seem like much but that's a lot of extra typing over the
course of a career.

~~~
WorldMaker
There is a growing number of us moving away from semicolons. I find Typescript
useful as the language is (of course) ASI-aware and you can double check that
the Typescript compiler's output looks about how you would "expect it". ESLint
and TSLint both now have semicolon never options and StandardJS is a simple
NPM install standard away towards such an ESLint configuration.

Yeah, pretty much the only "rules" are to know never to add a line break after
keywords such as return (which is the same rule as languages such as Python
and which is also something you have to know, regardless of semicolons) and
the "Winky Frown Rule": (, [, and ` all have to be winky frowns if you start a
line with one: ;(, ;[, ;`

It's pretty liberating writing JS/ES/TS without semicolons, and with ES2015
syntax things, makes the language feel like Python or an OCaML relative (which
it sort of is).

------
pbreit
I don't mind putting them in (not really true) but am still not always certain
where they go.

~~~
Cthulhu_
You should install eslint or a similar tool; they have configurable warnings
about things like that and will tell you where you should be putting
semicolons.

------
erikpukinskis
Meh. I don't use semicolons at all in JavaScript, except in for loops. I've
never once had a bug from it.

I'll stick to caring about he myriad issues that actually cause quality
problems for me rather than worry about obscure theoretical bugs.

------
Wintamute
Are Semicolons Necessary in JavaScript?
[https://www.youtube.com/watch?v=gsfbh17Ax9I](https://www.youtube.com/watch?v=gsfbh17Ax9I)

------
gregmac
Obligatory:
[https://pbs.twimg.com/media/B5LU4F7CUAELcIU.png](https://pbs.twimg.com/media/B5LU4F7CUAELcIU.png)

------
iLemming
OMG. Reasonable people already learned that Clojurescript, Elm and Purescript
are much, much, much better, so why are you still debating about semicolons?

------
draw_down
My team doesn't use them (except in a for-loop), hasn't for years, and it's
never actually been a problem. Folks need to let this one go, imo.

~~~
musha68k
I'm with you and I will stoke the fire now that we are in full "productivity"
mode:

Tabs or spaces?

Brains are wired differently plus we "higher" monkeys take our habits
seriously serious!

------
swang
I will write the function,

While you go have a beer

Where is my module support?

Where is my linter library?

Where is my code ending?

Where have all the semicolons gone?

\--- Sing to Paula Cole's "Where have all the Cowboys Gone?"

------
amelius
When I click on the link, I get "Error establishing a database connection".
Probably a semicolon missing somewhere.

------
alexandrerond
Why is this discussion always attached to JavaScript and not to Ruby or Go?

------
soyuka
they don't matter unless necessary

------
spinningarrow
Knowing what you're doing matters.

------
musha68k
Feelings matter

------
proksoup
I like working on code bases without semi colons better than those with,
because the choice to drop is indicative of the team's attitudes, and I often
find many other things I like about those softwares.

The rules to drop them are simpler than the rules to keep them.

~~~
__david__
> The rules to drop them are simpler than the rules to keep them.

Hmm. "Semi-colon at the end of each statement" is a pretty easy rule, and I
think it'll be hard to top that in simplicity. But I'm open if you've got one.

~~~
proksoup
Hm, there are statements where it's not required, like function
definitions[1], so it's more confusing than just "after each statement", no?

[1] [http://stackoverflow.com/questions/1834642/why-should-i-
use-...](http://stackoverflow.com/questions/1834642/why-should-i-use-a-
semicolon-after-every-function-in-javascript)

