javascriptで行末のセミコロンは省略すべきでない

最近のフレームワークでは省略するコーディングルールが採用されていることが多いが、省略すべきでないと思う。
なぜならば、行頭が [ や ( の場合に正しく動作しないことがあるから。
文法エラーになるだけならともかく、意図と異なる正常なコードだと解釈されるパターンがある。
例えば以下。

var a,b,c
a = "a"
[b, c] = ["b", "c"]
console.log(a, b, c) // 結果は『["b", "c"], undefined, undefined』になる
// 行末にセミコロンがついていれば結果は想定通り 『"a", "b", "c"』になる

こうなってしまう原因は以下のように解釈されているから。

var a,b,c;
a = "a" [b, c] = ["b", "c"];
console.log(a, b, c);

`a = "a" [b, c] = ["b", "c"];` は `a = ("a"[(b, c)]) = ["b", "c"];`という評価をされる。
すなわち、"a"のundefinedプロパティ(b, cを評価した結果はundefinedなので)に["b", "c"]を代入し、さらにaに["b", "c"]を代入せよ……である。
結果としてaには["b", "c"]が代入され、bとcには何も代入されないという想定外の動作になる。
これは普通にコードを書いていて発生しうる。



上記問題を防ぐために

a = "a"
;[b, c] = ["b", "c"]

……のように記述せよというルールもあるらしいが、正気とは思えない。
少なくともlintなどで自動チェックを行っていないプロジェクトでは、セミコロンを省略するコーディングルールを採用すべきでない。



セミコロン関係ではreturnが問題視されることもあるが、これはセミコロンを付けるルールでも付けないルールでも発生する問題なのでここではあまり関係ない。

// この書き方だと1行目が「return;」と解釈されるので戻り値はundefinedになる。
return
  {
    prop1,
    prop2,
  };
// こう書けば意図どおり { prop1, prop2 } を戻り値にできる。
return {
    prop1,
    prop2,
  };