定数を大文字にするのはどんなときか


定数？
とりあえず大文字で書いときゃいいんだよ。
というのはよくないらしいですよ。

以下は[When to capitalize your JavaScript constants](https://medium.freecodecamp.org/when-to-capitalize-your-javascript-constants-4fabc0a4a4c4)の日本語訳です。


# When to capitalize your JavaScript constants

JavaScriptスタイルガイドの多くは、定数を大文字にすることを推奨しています。
個人的に、この規約が正しく使われるべきところで正しく使われるところを見たことがほとんどありません。
その理由は、"定数"の定義がはっきりしていないためです。
この規約について詳しくなるため、もっと掘り下げることを決意しました。

## How do we define the term "constant"?

プログラミングにおいては、定数は変化しないものとされています。

> [It is a value that cannot be altered by the program during normal execution.](https://en.wikipedia.org/wiki/Constant_%28computer_programming%29)

JavaScriptは、変更できない値を宣言する方法を提供しているのでしょうか。
それに答える前に、定数規約のルーツを探してみましょう。

## The capitalization convention has roots in C

定数規約はC言語が由来です。
Cはコンパイル言語です。
すなわち、実行前に全てのコードは機械語に変換されます。

いっぽうJavaScriptはインタプリタ言語です。
実行時にはインタプリタがコードを1行ずつ読み取って逐次実行します。

コンパイル言語とインタプリタ言語の違いは、定数の定義について決定的な違いをもたらします。

C言語では、変数を以下のように宣言します。

```c:C
	int hoursInDay = 24;
```

また、定数の宣言はこうです。

```c:C
#define hoursInDay 24
```

これは記号定数とも呼ばれ、char、string、数値を定義することができます。
これらはプリミティブ値とも呼ばれます。
JavaScriptのプリミティブ値はstring、数値、真偽値、null、undefined、symbol、bigintです。

それではコンパイルの動作を見てみましょう。

C言語では、コンパイル前にプリプロッセッサが動作します。
プリプロッセッサは記号定数を全て、その値に書き換えます。
コンパイラは、プログラマがhoursInDayを書いたことを知りません。
コンパイラには`24`しか見えていません。

大文字の使用は、それが本当に定数であるという意味を表すことができます。

```c:C
#define HOURS_IN_DAY 24
```


## JavaScript constants are different than symbolic constants

ES6以前は、変化の無い値を使いたい場合でも、全てが変数でした。
大文字の使用は、値が変更されないという意思表示の助けになりました。

```javascript:JavaScript
var HOURS_IN_DAY = 24;
var hoursRemaining = currentHour - HOURS_IN_DAY;
var MY_NAME = 'Brandon';
MY_NAME = ... // 変更するのやめて！
```

ES6において、正確な意味では定数ではない`const`が導入されました。

ES6では変数の意味を意図的に使い分ける方法として、`const`および`let`が追加されました。
それでは大文字はどうすればよいでしょうか。

・`const`を使っていればその変数は同じままだという意図は明らかなので、別に大文字にする必要もない。
・`const`で宣言したものはすべて大文字にするべき。

`const`は、その値への読み取り専用の参照を作成します。
これは、その値が不変であるという意味ではありません。
[変数識別子に再割り当てすることはできない](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)、というだけのことです。

つまり、`const`の中身は変化することもあります。

```js:JavaScript
const firstPerson = {
  favoriteNumber: 10,
};

const secondPerson = firstPerson;
console.log(secondPerson.favoriteNumber); //10

firstPerson.favoriteNumber +=1;
console.log(secondPerson.favoriteNumber); //11
```

この例は、`const`が値の不変を意味するわけでは無いことを示しています。
オブジェクトのプロパティ書き換えを行うことはできます。
覚えておきましょう。
オブジェクトは参照渡しです。

```js:JavaScript
const secondPerson = 'Me'
secondPerson = 'something else'; // TypeError: Assignment to constant variable
```

そのため、JavaScriptでは単にconstの有無だけで定数であるか否かを区別することはできません。
定数かどうかを判断するには更にふたつの調査が必要です。

・値がプリミティブ値である
・プログラム全体を通して同じ値である必要がある

両方がイエスであるならば、`const`で宣言するべき(SHOULD)で、大文字にしてもよい(MAY)です。

`MAY`であることに注意してください。
定数を大文字にするという規約は、真の定数を持っている他言語から来ています。
JavaScriptは、少なくとも完全な意味での定数を持ってはいません。
定数を大文字にするという規約が意外と多くない理由はこれかもしれません。
Airbnbは定数について、[セクションを割いて解説しています](https://github.com/airbnb/javascript/#naming--uppercase)。

重要なことは、JavaScriptで定数を定義する際には、プログラマの意図を含める必要があることを認識することです。

もっと言うと、ある言語で絶対的な規則だったものが、別の言語でも有意義なものになるとは限りません。
最後に、IDEが現在のような高性能なものになる以前は、どこまで規約に従っていたのか、私にはわかりません。
私のIDEは、私が少し間違うとすぐにたくさん警告をしてきます。

読んでくれてありがとう。
[Twitter](https://twitter.com/Brandonwoz)もフォローしてください。

## Notes

私がこれらの例に`PI`を使わなかったことを訝しむかもしれません。
アクロニム、その中でも特に2文字のものは、慣例によって常に大文字もしくは常に小文字にする傾向があります。


# コメント欄

「Cのコード間違ってる。Cの大文字は定数ではなくプリプロセッサに対する慣習。プリプロセッサはスコープとか全く気にせずテキストを機械的に置換するだけ。」「ありがとう修正した。」
「10+1は11では？」「ありがとう修正した。」

※本文は修正後のものなので、修正前がどのようなものだったかは不明。


# 感想

`Remember: objects are pass-by-reference.`
参照警察が来るぞ！！

PHPでは[private const](https://qiita.com/rana_kualu/items/476385b674d27339f911#support-class-constant-visibility)というのがあって、私はクラス内定数をばきばき大文字で書いてます。
PHPの場合、constにはプリミティブ値しか入れられないので、(通常の手段では)後から変更される恐れもありません。

```php:PHP
class HOGE{
	private const FOO = 'BAR';
}

echo HOGE::FOO; // Cannot access private const
```

しかし、本文からもリンクされている[Airbnbのコーディングスタイルガイド](https://github.com/airbnb/javascript/#naming--uppercase)では、(1)exportする、(2)constで定義された変数であり、(3)プロパティも含めて変更されることが無いことを前提にしている、を全て満たす場合にのみ大文字を使用してもよい(MAY)、となっています。

つまり、Airbnbのコーディングスタイルガイドに従うと、このようなローカル定数は一切大文字にしてはいけないということになります。

これはかなり意外だと感じたのですが、そのことについて言及している日本語記事は全く見当たりませんでした。
みんなAirbnbコーディングスタイルガイドは参考にしてないのか？
それともJavaScript界隈では既に常識だったりするんですかね？

ちなみに[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const)では`慣例的にすべて大文字`と書いてあります。