To make semicolon rules simple
Every line that begins with a (
, [
, `, or any arithmetic operator, must begin with a semicolon if you want it to be interpreted as its own line ~ Otherwise, it may combine with the previous line by accident. All other line breaks have implicit semicolons.
That's it. Done.
Note that /, +, - are the only valid operators you would want to do this for anyway. You would never want a line to begin with '*', since it's a binary operator that could never make sense at the beginning of a line.
You should put the semicolons at the start of the line when doing this. You should not try to "fix" the issue by adding a semicolon to the previous line, or any reordering or moving of the code will cause the issue to potentially manifest again. Many of the other answers (including top answers) make this suggestion, but it's not a good practice.
Why do those particular characters need initial semicolons?
Consider the following:
func()
;[0].concat(myarr).forEach(func)
;(myarr).forEach(func)
;`hello`.forEach(func)
;/hello/.exec(str)
;+0
;-0
By following the rules given, you prevent the above code from being reinterpreted as
func()[0].concat(myarr).forEach(func)(myarr).forEach(func)`hello`.forEach(func)/hello/.forEach(func)+0-0
Additional Notes
To mention what will happen: brackets will index, parentheses will be treated as function parameters. The backtick would transform into a tagged template, regex will turn into division, and explicitly +/- signed integers will turn into plus/minus operators.
Of course, you can avoid this by just adding a semicolon to the end of every linebreak, but do not believe that doing this can let you code like a C programmer. Since it is still the case that when you don't end a line with a semicolon, Javascript might implicitly add one on your behalf against your desires. So, keep in mind statements like
return // Implicit semicolon, will return undefined.
(1+2);
i // Implicit semicolon on this line
++; // But, if you really intended "i++;"
// and you actually wrote it like this,
// you need help.
The above case will happen to return/continue/break/++/--. Any linter will catch the former case with dead-code, or the latter case with ++/-- syntax error.
Finally, if you want file concatenation to work, make sure each file ends with a semicolon. If you're using a bundler program (recommended), it should do this automatically.