JavaScript のvar、let、const 修飾子の違いについて

変数の宣言方法

JavaScript の変数の宣言方法は3パターンです。varletconstとなります。

var x = 1;
let y = 2;
const z = 3;

varletconst 修飾子共通の仕組みですが、変数同士を,(カンマ)で区切ることにより、同時に複数の変数を定義できます。

var x = "JavaScript",
y = "JS";

これは次のように書いた場合と同じ意味になります。

var x = "JavaScript";
var y = "JS";

var 修飾子

var 修飾子は値の再代入が可能です。varlet 修飾子はほとんど同じ振る舞いになります。

var x = "JavaScript";
x = "JS";

var 修飾子は初期値がない変数として宣言できます。

var x;
x = "JavaScript";

let 修飾子 [ES2015(ES6)以降]

let 修飾子は値の再代入が可能な変数を宣言できます。 let の使い方は var とほとんど同じです。

let y = "JavaScript";

let 修飾子は初期値を指定しない変数を定義できます。初期値がない場合は「undefined」という値が入ります。
const 修飾子は初期値を指定しないとエラーになります。

let y;
// yは自動的に undefined という値が入る

let 修飾子で宣言した変数は何度でも値の代入ができます。

let y;
y = 1;
y = 2;
y = 3;

const 修飾子 [ES2015(ES6)以降]

const 修飾子は、再代入できない変数の宣言と値(初期値)を定義できます。

次のように、const 修飾子に続いて変数名を書き、代入演算子(=)の右辺に変数の初期値を書いて変数を定義できます。varlet 修飾子とは異なり初期値の設定は必須となります。

const 変数名 = 初期値;
const z = "JavaScript";

const 修飾子で宣言した変数に対して、後から値を代入することはできません。
再定義した場合はエラーとなります。

const z = "JavaScript";
z = "JS"; // => TypeError: invalid assignment to const 'z'

変数を再定義しない定数を宣言する場合に使用してください。
varlet 修飾子でも代替可能ですが、不意に異なる値を代入してしまい不具合の要因となりますので、明示的に const 修飾子を使用することを推奨します。

後に値を代入する可能性がある変数やループ処理に使用する変数に関しては let 修飾子を使用しましょう。

const 修飾子は定数ではない

const 修飾子は「再代入できない変数」を定義する変数宣言であり、定数を定義するわけではありません。

JavaScriptではオブジェクトなども const 修飾子で宣言できます。 次のコードのように、オブジェクトという値そのものは、初期化したあとでも変更できます。

// const 修飾子でオブジェクトを定義している
const object = {
    key: "値"
};
// オブジェクトそのものは変更できてしまう
object.key = "新しい値";

このように、const 修飾子で宣言した変数が常に同じ値を示すとは限らないため、定数とは呼べません 。
そのため、const 修飾子の宣言は「再代入できない変数」を定義すると理解しておくのがよいでしょう。

var と let の違い

var 修飾子は let 修飾子とよく似ていますが、var 修飾子には同じ名前の変数を再定義できてしまう問題があります。

let 修飾子や const 修飾子では、同じ名前の変数を再定義しようとすると、次のような構文エラー(SyntaxError)が発生します。 そのため、間違えて変数を二重に定義してしまうというミスを防ぐことができます。

// "x"という変数名で変数を定義する
let x;
// 同じ変数名の変数"x"を定義するとSyntaxErrorとなる
let x; // => SyntaxError: redeclaration of let x

一方、var 修飾子は同じ名前の変数を再定義できます。 これは意図せずに同じ変数名で定義してもエラーとならずに、値を上書きしてしまいます。

// "x"という変数を定義する
var x = 1;
// 同じ変数名の変数"x"を定義できる
var x = 2;
// 変数xは2となる

各修飾子の違いを比較

varletconst
初期値なし
再宣言
再代入
スコープ関数ブロックブロック
変数の巻き上げundefinedエラーエラー