ES6時代のコーディングスタイルを考える

ここではコーディングスタイルを考える上で、ES6（ECMAScript2015)の以下の特徴に注目して考察するものです。

- 変数宣言は、`const`を基本とする
- クラス宣言文や関数宣言文はブロックスコープ
- 文字列では、テンプレートリテラルを活用する
- ジェネレータのために、複数の構文が拡張された

また、以下の基準を採用していることを特に触れておきます。

- ES5コードの混在、ES5時代のスタイルとの互換性は取らない
- ES6 modulesが存在しない状況で適用可能なスタイルを取る
- 視認性を犠牲にコーディング時のミスの影響を隠蔽するスタイル([ヨーダ記法](https://ja.wikipedia.org/wiki/%E3%83%A8%E3%83%BC%E3%83%80%E8%A8%98%E6%B3%95)など)は取らない
- 局所視認性より、全体視認性での高さを重視する
    - 微妙に違うものを区別しやすいスタイルにする
    - 同じものは同じスタイルを取る
    - 一覧しやすくコンパクトに書ける方を採用する

# 変数宣言は、`const`を基本とする

ES6では再代入を認めない`const`変数が導入されました。そしてビルトインの機能も合わせて、コード中の変数の大半は`const`変数で済むようにできる状況になりました。

## 変数は、その利用範囲がなるべく小さくなるように用いる

- 変数は、使う場所のなるべく近くで宣言する
- 可能な限り`const`変数を基本とし、そうできない場合に限り再代入可能な`let`変数にする
    - `var`変数はグローバルコンテキストに影響させる目的でのみ用いる(関数内では用いない)
    - `for-of` ループでは、`const`変数を用いる
- 変数1宣言文での複数変数宣言は、論理関係で同等になるもの(`x`と`y`、`width`と`height`など)だけでまとめるとよい

ES5以前の`var`変数には、関数スコープおよび宣言部のhoisting(巻き上げ)があって、その存在が有名なコーディングスタイルに大きく影響を与えていました。とりわけ、変数宣言を関数の頭にまとめるスタイルは、モダンなプログラミング言語で行う**「変数の影響範囲をなるべく小さくする」**コードデザインを阻害し、しかも複数箇所で同名変数を再利用する可読性の低いコードが量産しました。`const`変数では、このような頭での一括宣言自体が不可能になります。

`const`及び`let`変数は、その範囲をなるべく小さくなるよう宣言します。なるべく後ろ側に、変数を使う式に近いところに配置します。このため変数宣言は、その論理的な意味の違いによって、ブロック内の別々の位置に来ることが基本です。

(`for of`ループでの`const`変数の利用は、firefoxで長らく使用できない状態でした。firefox-51にてやっと利用可能になったようです。)

## インデントは2スペース

- 2スペースのインデントを用いる
- `const`宣言文の折り返しは6スペース、`let`宣言文の折り返しは4スペースを用いる

`const`が5文字であるため、宣言文で複数の変数で折り返して記述する場合、6スペースで折り返すと変数の頭が揃います。４スペースだと`const`宣言文の折り返しだけが行頭が違う状況になります。

# クラス宣言文や関数宣言文はブロックスコープ

- 関数オブジェクト式を与える変数宣言文ではなく、関数宣言文を用いることを考える

クラス定義や関数定義分も変数同様ブロックスコープになりました。

ちなみに、引数のデフォルト値の式は、関数内(の頭)で順に評価されるコードです(Pythonのような宣言時で1回の評価ではない)。値でキャプチャしてるわけではないので、副作用のある変数を使う場合には注意すること。

```js
// tail call recursion
function uniq(A, i = 0, r = [], h = A[i], l = r.length) {
  if (i === A.length) return r;
  return uniq(A, i + 1, l === 0 ? [h] : h === r[l - 1] ? r : [...r, h]);
}

console.log(uniq([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])); //=> [1, 2, 3, 4]
```


# 文字列では、テンプレートリテラルを活用する

- 文字列リテラルは、ダブルクォート`"`を基本で用いる
- 文字連結は、`+`を使わず、すべてテンプレートリテラルで行う
- シンボル用途は、なるべく文字列を使わず、`Symbol`値を用いる

ES6では、バッククォートでくくった文字列を作るテンプレートリテラル構文が、追加されました。テンプレートリテラル内には`${式}`を記述でき、その式の評価値から文字列が展開されます。

文字列の結合では、`+`や`Array`に入れて`join('\n')`を用いたスタイルが使われていたが、テンプレートリテラルはその用途を広くカバーすることになります。

```js
const line = `${name}: ${value}`;
```

またES5のコーディングスタイルでは、HTML属性との兼ね合いから、シングルクォート`'`を基本にする文字列を採択するものが多いが、シングルクォートと(シンタックスハイライトを行っていても)バッククォートとの識別性が、とくにターミナル上で、悪いという欠点があります。

また、シングルクオート文字列をシンボルの代わりに用いるスタイルも存在します。この場合は、クォート文字で区別するのではなく、ES6で追加された`Symbol`を用いるのが望ましいです。

```js
const localProps = Symbol`props`;
```

のように、テンプレートリテラルでシンボルを書くことも可能でしょう(式展開は使えないが、シンボルなら文字列埋め込みのほうがよい)。

# ジェネレータのために、複数の構文が拡張された

- `function *()`や`yield *iter`ではなく、`function* ()`、`yield* iter`を用いる
- オブジェクトやクラスのメソッド構文でのジェネレータは、`* method()`や`* [method]()`ではなく、`*method()`、`*[method]()`を用いる

`function`のあとの`*`のあるなしではなく、`function*`の時点で、ジェネレータであると識別できることを重視した。

ちなみに`yield*`式の評価値は、(pythonの`yield from`同様)ジェネレータの`return`の値が得られる。`Array`など普通のイテレータでは`undefined`になる。

# その他

- 一括代入文は、カンマ式ではなく、`Array`のdestructuringを使う

```js
// euclidean algorithm
while (b > 0) [a, b] = [b, a % b];
```

- 1引数アロー関数式の括弧の省略

```js
const len = (str) => str.length; //代入式の右辺の場合、括弧を入れておく
["a", "ab", "abc"].map(s => len(s)); //引数の場合、括弧は省く
```

- `method.bind(this)`は使わず、アロー関数`() => this.method()`を使う

- 使わない引数名には`_`や`_1` (ブロック内でlodash等は使わない前提)

- オブジェクトの情報隠蔽は、`class`ではなく、`Proxy`を使う

# 追記: 実行速度に関して

シンプルなコードは、最速なコードではないでしょう。極端な話をすると、JavaScriptの実行環境では、`Array`にアクセスするコードは、[ループを変数で展開する](https://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%BC%E3%83%97%E5%B1%95%E9%96%8B)と実行時間が大幅に短くなるが、コードの量とその複雑度は上がります。

しかし普通は、小さくシンプルであるほうが読みやすく、なによりバグが入る隙が小さいです。そして実行速度第一で書いたつもりの未成熟なコードとくらべても、小さなコードは十分速いでしょう。たとえば上述の`uniq`はたった4行だけど末尾再帰です。速いつもりではじめから書かれたコードで実際どれだけ速いでしょうか。

プログラムは、「任意の入力データと結果の間の全体関係」の記述という側面があります。それは処理中の状態でも常に成立する関係(不変条件invariant)であり、それこそが処理の正しさの源です。シンプルなコードというのは正しさがその記述から自明であることです。この`uniq`でいえば、「要素が一つ増えた時(`i + 1`で`h = A[i]`)に、最後の値と同じ値だった場合(`h === r[l - 1]`)はそのまま(`r`)が、違う場合では最後にその値を追加したもの(`[...r, h]`)が結果である」が任意の入力全体に対して成り立つのが`uniq`の意味の本質であって、(そこに「最後の値」がない最初の状況での関係を加えたうえで)再帰呼び出し部分にそのまま記述しています。

これを表現するのに何行もあるとどうでしょう。その構成要素である変数が長い範囲に散らばってたら、正しいこと(もしくはバグが入った時どこが間違ってるか)を判別するのにどれだけかかるでしょうか。