JavaScriptのconst, let, varの違い。(初学者向け)

##はじめに
JavaScriptのconst / let / var の違いについて初学者向けにまとめてみました。
またJavaScript ES2015以降では基本的にはconstを使うように推奨されています。そこで後半はconstの定義方法についてまとめてみました。興味がある方はそちらも合わせて読んでみて下さい。

##目次
・変数と定数
・再定義、再代入とは
・スコープ
・以上！
・const編
・なぜconstが追加されたのか
・constは定数なのか
・constの挙動
・以上!
・おまけ
・参考記事

##変数と定数
const / let / var の違いを知るにはまず変数と定数の違いについて知る必要があります。
###変数とは
ざっくりいうと変数とは、データを入れておくための「箱」で中の値が変化するものです。
JavaScriptではvarとletにあたります。
###定数とは
定数は変数と違って中の値が変化しないものです。
JavaScriptではconstにあたります。
正確に言うとプリミティブ値の場合は定数。
↑ここは後半constの定義の仕方の項目で記述しているので焦らなくて大丈夫です。
#挙動の違いを見てみよう
###varの場合
```javascript:qiita.js
var a = 1;
console.log(a); //1
var a = 2;
console.log(a); //2
a = 3;
console.log(a); //3
```
varは変数ですので値が変わっていますよね！！
よってvarは再定義・再代入可能となります。
再定義と再代入がわからない方も後述しているので安心してください:ok_hand:

###letの場合
```javascript:qiita.js
let b = 1;
console.log(b); //1
let b = 2;
console.log(b); //Error
b = 3;
console.log(b); //3
```
letも変数ですが2つ目の再定義の部分がErrorになっています。
よってletは再代入は可能だが再定義は不可となります。

###constの場合
```javascript:qiita.js
const c = 1;
console.log(c); //1
const c = 2;
console.log(c); //Error
c = 3;
console.log(c); //Error
```
最後にconstですが２つ目3つ目がErrorになっています。
よってconstは再定義・再代入不可となります。

###まとめると
|   |var  |let  |const |
|------|------|------|------|
|再定義|○|×|×
|再代入|○|○|×


#再定義、再代入とは
察しの良い方はもうお気づきかもですが。再定義とは変数、定数を型に沿ってもう一度宣言し直すことで、再代入とは変数名だけを宣言して値を入れ直すことです。
具体的に
###再定義
```javascript:qiita.js
let d = 1;
let d = 2;
let d = 3;
const e = 1;
const e = 2;
const e = 3;
```
もちろんletとconstは再定義不可なのでErrorとなります。
###再代入
```javascript:qiita.js
let f = 1;
f = 2;
f = 3;
const g = 1;
g = 2;
g = 3;
```
constはErrorとなります。

#スコープ
スコープとは変数がどの場所から参照できるのかを定義する概念です。
簡単に言えば実行されるコードを参照できる範囲のことです。
そしてブロック({})の中で囲われたlet,constはブロックの外側からはアクセスできず、ブロックの内側からのみアクセス可能なローカル変数になります。これを「ブロックスコープ」と言います。
聞くより実際に見た方が早いと思うのでvar,let,constそれぞれのスコープを見ていきましょう！

###varの場合
```javascript:qiita.js
{
   var a = 1;
   console.log(a);//1
}
console.log(a);//1
```
varはブロックスコープがないのでブロック外でも値の参照ができます。

###letの場合
```javascript:qiita.js
{
   let b = 2;
   console.log(b)//2
}
console.log(b);//error
```
letはブロックスコープなのでブロック外では参照できません。
###constの場合
```javascript:qiita.js
{
   const b = 3;
   console.log(b)//3
}
console.log(b);//error
```
constもブロックスコープなのでブロック外では参照できません。

###まとめると
|   |var  |let  |const |
|------|------|------|------|
|ブロックスコープ|×|○|○
#以上！！
以上ここまでがconst/ let/ var の違いとなります。
ここからはconstの定義方法についての記事になります。と言いますのも冒頭書いた通り2021年現在ではループ等でプリミティブ値を再代入したい場合など以外はconstで定義することが推奨されているのです。
そこで今回はconstについて少し深ぼっていきたいと思います！

##const編
constを知るにはまず何故constが追加されたのかを知る必要があるでしょう。では早速。

###なぜconstが追加されたのか
JavaScriptには初めvarしかありませんでした。そしてvarは意図しない動作を作りやすい問題が知られています。つまり不具合の温床になりやすいのです。
そこでvar自体を改善するのではなく新しくconstとletというキーワードを追加することで、varの問題を回避できるようにしました。var自体の動作を変更しなかったのは、後方互換性のためです。つまりvar宣言したものによって作られている既存のアプリケーションが動かなくなるためvarを残したのです。
ここでわかる通りvarは必要ないが既存のアプリが動かなくなるわけにはいかないので仕方なく残していると言うことそしてこれからはlet,constを使って宣言しましょうねということです。

###constは定数なのか
結論からいうと一応定数です。この一応というのは前述したプリミティブ値以外が格納された場合は値が変わってしまうからです。
え？定数は値が変わらないことを指すんじゃないの？まずプリミティブ値ってなんなの？？
わかります。混乱してしまいますよね。でも大丈夫です。一つずつ丁寧に解説していきます。

###プリミティブ値とは
プリミティブ値とはズバリ基本型の値のことです！！
は？と思われた方もおられると思うので説明するとJavaScriptには基本型と参照型があります。
基本型と参照型がわからない方は下記の記事を参照してください。
<a href="https://qiita.com/Tateishi0819/items/51777538dacf0bc7cbc1">(JavaScript) データ型と参照型</a>
プリミティブ値 = JavaScriptの基本型と覚えてもらって大丈夫です。

###constの挙動
プリミティブ値を理解してもらったところでここからは本当にプリミティブ値以外の時には値が変わるのかを実際の挙動を見ていきましょう！

```javascript:qiita.js
const h = 1;
console.log(h);//1
h += 2;
console.log(h);//Error
```
今まで通りプリミティブ値の場合は定数として機能しているようですね。では配列(参照型)の場合を見てみましょう。

```javascript:qiita.js
const i = [1,2,3];
console.log(i);//[1,2,3]
i[0] += 2;
console.log(i);//[3,2,3]
```
a[0]の値を+2することができました。
もちろん今まで通りこちらの参照型以外の場合は再代入できないので注意してくださいね。


##以上！
お疲れさまです以上const編になりました！ここまで少し長かったかと思いますがvar,let,constについてまたconstの習性について理解が進んだんじゃないかなと思います。最後に今回参考にした記事またもっと深く知りたい方向けに良記事を見つけたので貼っておきます。

##おまけ
これまでの話を踏まえてconstは大文字で定義するべきかについておまけ程度に書いてみました。
なんとなく予想立っている方もいると思いますが結論から言いますとプリミティブ値の場合は大文字で定義しても良いです。ただあくまでしても良いです。
なのでまとめるとプリミティブ値を代入する場合は完全に定数として扱うので大文字で定義してもよい。それ以外は完全に定数とは言い切れないので小文字で定義する。です！
重要なのはJavaScriptで定数を定義する際には、プログラマの意図を含める必要があることを認識することです。

##参考記事
<a href="https://qiita.com/kiyoshiro/items/13c60fad1f5279993fa2">JavaScriptからletを絶滅させ、constのみにするためのレシピ集</a>
<a href="https://qiita.com/rana_kualu/items/e912d94cebd5c7ef73af#:~:">定数を大文字にするのはどんな時か</a>