【基本はlet】var, let, constの違いを解説【JavaScript】
JavaScriptで変数を使用する場合、宣言する記述として昔から”var”がよく使われていますよね。
しかし、近年ではvarのほかにletやconstといったデータの宣言方法も使用頻度が高まっています。それぞれ、いったいどのような違いがあるのでしょうか。
今回は、そんなvar、 let、 constの違いを、具体的なプログラム例を交えつつ解説していきます。
各宣言方法の使用例
var、let、constは、どれもデータの記憶域(データを留めておくもの)を宣言する際に使われる記述であり、コードとして記述する際、その書き方に大きな違いはありません。
実際に使用する場合、以下のように記述します。
// 「型 変数名 = 代入するデータ」
var thisVar = 1;
let thisLet = "私がレットです。";
const thisConst = ["this", "const"];
console.log(thisVar);
console.log(thisLet);
console.table(thisConst);

上の例を見ると、どれもデータを入れたり、逆にデータを取得できたりするのがわかります。
上記のサンプルコードでは、それぞれの特色は一切現れません。そのため、通常のプログラムでは実務レベルの業務であっても、変数の宣言方法が明確に使い分けられているケースは非常に稀です。
これからそれぞれの違いについて解説していきますが、別に使い分けなくてもvarだけ扱っていればプログラムは作れるというのが、結論になってしまいます。
そもそも、「varだけ使っててダメなことありますか?」と言われると、何も言い返せません。
JavaScriptはこういった変数の宣言に関するルールが曖昧なのも、初心者が扱いやすい理由です。
それぞれ何が違う?
前述のとおり、データを宣言し、その後宣言したデータを使いまわす点では、それぞれの役割にそれほど違いはありません。
しかし、言語内に3つの宣言方法が存在しているということは、異なる役割を担っているということです。ここからは、それぞれの宣言方法にどういった違いがあるのか、詳しく解説していきます。
変数と定数
3つの宣言方法は、定義するデータの記憶域が、変数か定数かで分別できます。
- 変数・・・データを参照・変更することが可能
- 定数・・・参照はできるが、変更することができない
それぞれの宣言方法を当てはめると、
- 変数・・・var、let
- 定数・・・const
となります。要するに、varとletはデータの中身を変えられる記憶域を定義するもので、constは逆に記憶域を変更できない、変更されたくない定型的なデータの記憶域を定義できる記述なのです。
実際に、プログラムでそれぞれの動作を確認してみましょう。
まず、varとletの動きについて確認してみます。
var thisVar = 5;
let thisLet = 5;
thisVar += 5; //thisVarに5を足して代入
thisLet += 3; //thisLetに3を足して代入
console.log(`var: ${thisVar}`);
console.log(`let: ${thisLet}`);

varとletは、変数を定義した後、それぞれに5と3の数値を足すことができました。
では、constで同じような処理をしようとすると、どうなるのでしょうか。
const thisConst = 5;
thisConst += 1; //thisConstに1を足して代入;
console.log(`const: ${thisConst}`);

上の画像の通り、エラーを吐いてしまいます。エラー内容としては、「コードの3行目にタイプエラーがあるよ。定数に値は代入できないよ!」と言われています。
サンプルプログラムの3行目ですから、
thisConst += 1; //thisConstに1を足して代入
この代入処理でエラーが起きているということです。
つまり、constで定義した定数には後からデータを代入できないことがわかりますね。
もちろん、データの参照はできますし、定数に値を代入しなければ、足し算などの計算にも利用できます。
const thisConst = 5;
console.log(`参照だけ: ${thisConst}`);
console.log(`参照+計算: ${thisConst + 5}`);

constで定義した定数にデータを代入する方法
先ほど、constで定義された定数には、後からデータを代入できないと説明しました。しかし、constに入っているデータに対し、後から別のデータを代入できる場合があります。
それは、定数としてオブジェクトを記憶した場合です。
以下のプログラムをご覧ください。
// Json
const thisConst = {
"number": 5
};
// Jsonの"number"に対応する数値「5」に5を足す。
thisConst.number += 5;
console.log(`参照: ${thisConst.number}`);
{ ・・・ }という書式で、中に「”キーの名前”: データ」と入力することで、オブジェクト形式でデータを作ることができます。
つまり、このサンプルでは、constで定義した定数としてオブジェクトを記憶し、その中にあるnumberの値に別の数値を代入しようとしているのです。
これまでの説明だと、同じようにエラーが起きそうなものですが・・・

エラーなどは一切起きず、何事もなかったかのように期待通りに動いてしまいました。
なぜこうなるのかというと、constで定義したオブジェクトは、あくまでも「オブジェクト」を記憶しただけで、その中にあるキーと値の内容まで記憶しているわけではないから。
要するに、オブジェクトがどういったものなのか、そういった上辺の情報だけを保持しているため、オブジェクトの中身は自由にいじれてしまうということです。
オブジェクトを定義する際に、「値を変えられたくないからconstで宣言しよう!」としても値は自由に変えられるので、注意してください。
データを使用できる範囲
var、let、constの違いとして、データ使用できる範囲(スコープ)の違いが挙げられます。変数というのは、データを記憶するための箱物であり、使える範囲に決まりがあります。
大きく分けると、varとlet・constの2つの分類に分けられます。
varはグローバル変数と呼ばれるタイプのもので、スコープの垣根がほとんどない、非常に自由な変数の一種です。逆にletやconstはローカル変数・定数と呼ばれ、varに比べてスコープの範囲が限られています。
説明してもわかりにくいと思うので、実際にプログラムを見ながら確認していきましょう。
varの「スコープの垣根がない」という特性を表すサンプルプログラムを以下のように作りました。
for(let i=0; i<=5; i++){
// forループの中で変数を定義
var number = i;
}
//forループの中で定義した
//変数numberを出力
console.log(`number: ${number}`);
forループの中で変数を定義し、それをループの外で呼び出す処理です。実行してみると、以下のように結果が返ってきます。

一方、varの部分を”let”に変えて変数を定義した場合どうなるかというと・・・

「numberというものは存在しません」と、エラーが返ってきました。
この結果を見ればわかるように、varはforループの中で宣言しても、ループの外から呼び出せますが、letやconstはforループの外から呼び出すことができません。スコープの違いについて、わかりやすく結果に差が出ていますよね。
以下のようにforループの外で変数を定義してから代入処理をループの中で行うようにすれば、letでも同じような結果が返ってきます。
// 数値代入用の変数を用意
let number;
for(let i=0; i<=5; i++){
// forループの中で変数を定義
number = i;
}
//forループの中で定義した
//変数numberを出力
console.log(`let number: ${number}`);

基本は「let」がおすすめ
昔はvarだけを使ったコードが多かったですが、現在はデータを定義する際にはletを扱うのが主流です。
varと比べて関数内などで定義しても周りのプログラムにトラブルが発生することがなく、安心して新しいデータを定義できます。
constは値を変更したくないデータや、オブジェクトなどデータの集合を定義する場合(重要性が高いデータの定義)に用いると、より可読性の高いコードになります。
まとめ
var・let・constは、それぞれデータを記憶するために使用しますが、定義後のデータの取り扱いやスコープの広さなどに大きな違いがあります。それぞれの違いを理解し、適切に扱えるようになれば、プログラマとして一歩成長することができるでしょう。