JavaScriptのセミコロンが必要なケース

セミコロン要らないって言うから消してたのに・・

JavaScriptは文末のセミコロンを省略しても、実行時に自動的に追加して解釈してくれるということで、最近は省略するようにしてました。
ところが、何も気にせず文末のセミコロンを全て削除して記述していたら、どうも動かないケースがでてきたので調べてみたところ、省略してはいけないケースがありました。

以下、エラーになります。

let cat = '😺'
let dog = '🐶'
let pig = '🐷'

(()=>{
    console.log(cat, dog, pig)
})()

// -> TypeError: "🐷" is not a function

豚行のみ、末尾にセミコロンを1つ追加すると、正常に処理されるようになります。

let cat = '😺'
let dog = '🐶'
let pig = '🐷';

(()=>{
    console.log(cat, dog, pig)
})()

// -> 😺, 🐶, 🐷

アロー関数 ()=>{} じゃなく function(){} でも同じです。 いろいろ調べてみると、どうやら即時関数は ( から始まるため、前の文の続きなのか別の文なのかわらなくなるみたいです。 つまり、前者は let pig = '🐷'(()=>{... と解釈され、 '🐷' は関数じゃないでよって怒られるわけですね。

ということは、 ( から始まるのであれば別に即時関数じゃなくてもエラーが再現できそうです。

let cat = '😺'
let dog = '🐶'
let pig = '🐷'

(1)

// -> TypeError: "🐷" is not a function

はい。同じエラーが出ました。理解は合っているようです。

解決策

解決策は3つあります。

  1. 素直な心ですべての文末にセミコロンを付ける
  2. ( から始まる文の一つ前の文末にセミコロンを付ける
  3. ( から始まる文の頭にセミコロンを付ける

1はそのままの意味ですので割愛します。
2は前述している方法です。(ok.js
3は、例えばこう書くことでエラーを回避できます。

let cat = '😺'
let dog = '🐶'
let pig = '🐷'

;(()=>{
    console.log(cat, dog, pig)
})()

// -> 😺, 🐶, 🐷

実はこの解決策のみ、セミコロンの他に !~ でも同様の効果があります。

...
!(()=>{
    console.log(cat, dog, pig)
...
...
~(()=>{
    console.log(cat, dog, pig)
...

! は理論値の反転、~ はビット演算子の反転です。このカッコの結果値は捨てる運命にあるので反転しようが関係なく、別の文であることがわかるスプリッタとしてのみ機能するという寸法です。面白いですね。

他にも使える記号がないか探したのですが、見つかりませんでした。 あったら教えてください。

セミコロン書くべき?書かざるべき?

ネット情報を漁っていると、セミコロンを書く派と書かない派とではっきり分かれているようです。
私は最近セミコロン書かないようになってきました。なんだかスッキリして気持ちいいんですよね。

一部では宗教並みに白熱する場合もあるようですが、そんなに気にしなくていいような気がしてます。セミコロン書かないとおかしくなるケースがあるとさえ分かっていれば、どっちでも対処できるはずですから。

参考にさせていただいたサイト