JavaScriptの3つある変数宣言、varとletとconstは、よく混乱を生みます。どれも変数を宣言することに変わりはないので、違いがわかりにくいのです。このことが初学者を混乱させている場面をたびたび目にしますし、プログラミングに慣れ親しんだ人でも役割を意識しないまま書いていることがあります。
そこでこの記事では、3つの変数宣言の役割とその使い分けについて、それぞれ簡単に紹介してみます。
3種類の変数宣言とその使い分け
var – 変数を宣言する
varは、JavaScriptにおいて変数を宣言する上で、最も基本的な方法になります。varで宣言された変数は関数スコープとなり、宣言のスコープ先頭への巻き上げ(Hoisting)が行われます。(※変数のスコープおよび巻き上げについてはここでは解説しません。)
var x = 10;
x = 20;
もともと、JavaScriptの変数宣言にはvarしかありませんでした。変数を宣言する唯一の方法だったのです。letとconstは新参者ということになります。よって古いブラウザでも何の問題なく動くのがこのvarになります。
しかし、現在ではvarを使う理由はありません。関数スコープおよび巻き上げのせいで、挙動の予測が困難になるからです。varを使うのは、古いブラウザを対象にした場合のみになります。モダンブラウザを対象にする場合は、varの代わりにletを使用してください。
let – 変数を宣言する(ブロックスコープ)
letは比較的新しい変数宣言の方法です。varと同じく変数を宣言できますが、letで宣言した変数はブロックスコープになります。巻き上げは行われますが、宣言前に参照するとエラーとなります。
let x = 10;
x = 20;
つまり、letは他のプログラミング言語における変数宣言とほぼ同じ動きをします。プログラマにとって直感的で、扱いやすい挙動をするということです。初学者にとっても、letは不思議な挙動をしないので、わかりやすいはずです。
letの用途は、varの代わりです。varでも変数は宣言できますが、letのほうが、よりわかりやすい動きをします。モダンブラウザを対象にしたコードでは、かつてvarを使っていた場面全てでletを使うことを推奨します。極めて特殊な処理をしていないかぎり、varをletに置き換えても問題は出ないはずです。
const – 再代入不可能な変数を宣言する
constはletと同時期に提案された変数宣言の方法です。letと同じくブロックスコープで、巻き上げは行われるが宣言前の参照がエラーになる点も同じです。ただし、constで宣言された変数は、再代入が不可能になります。
const x = 10;
x = 20; // 再代入はerror
注意したい点としては、他のプログラミング言語ではconstというキーワードはコンパイル時定数になることがほとんどですが、JavaScriptでは単に再代入不可になるだけということです。つまり、JavaScriptにおけるconstは、他のプログラミング言語におけるfinalと同じ動きをします。
constは、ほぼletと同じです。letとの違いは再代入が可能か否かだけです。constを使うのは変数への再代入が不要な場合、あるいは再代入されたくない場合になります。
つまり…
つまり、JavaScriptにおいて、実際に変数の宣言に使用するのは、letとconstだけということになります。varのことは忘れてしまってかまいません。再代入が必要な場合はlet、不必要な場合はconstを使用すればいいのです。
let vs. const
さて、varは脱落しました。残る問題はletとconstの使い分けです。再代入が必要か不必要か、どうやって見分けるのでしょうか。それぞれどんな場面で使用することになるのでしょうか。
再代入はほとんど必要ない
実は、実際のプログラミングにおいて、再代入というのはほとんど必要ないのです。あなたが今まで書いたプログラムを思い浮かべてください。変数を書き換える場面というのは、めったになかったはずです。
多くの変数は、一度値が代入されると、その値のまま生涯を終えます。簡単なプログラムを想像してみましょう。円の面積を求めるプログラムです。
const pi = 3.14;
const radius = 5;
const area = pi * radius * radius;
const message = `半径${radius}の円の面積は約${area}です。`;
console.log(message);
このプログラムに再代入は一切出てきません。それもそのはずです。まず、意味が異なる値には、それぞれ違う名前が割り当てられます。そして計算して値が変われば、意味も変わり、別の名前が割り当てられます。つまり、違う値が同じ名前に割り当てられることは、普通ありません。再代入は発生しないのです。
基本的にはconstを使用する
再代入が発生しない場面でletを使うのは得策ではありません。不必要な変数の再代入を許せば、バグの発生に繋がることがあります。また、コードの読み手に「この変数は値が変わる可能性があるのか?値の変化を追いかける必要がありそうだ」と不要な懸念を抱かせることになり、デバッグの手間も増えます。
以上のことから、変数の宣言には、基本的にはconstを使うことを推奨します。constを使うことで、値が変化しないという保証をすることができるのです。
再代入が必要になる(letを使用する)場面
逆に再代入が必要になるのは、どんな場面なのでしょうか。再代入は、主にイテレーション(繰り返し)処理が行われる場面で必要とされます。代表的な例としてはfor文があります。for文ではイテレータ変数(多くの場合iという名前が使用される)の値を増減させ、イテレーションを行います。このときに再代入が必要になります。
for(let i = 0; i < 100; i++) {
console.log(i);
}
ループ中にiの値が何度も書き換わっています。こういったときはletが必要になります。
ただしforループ内の変数宣言については、基本通りconstを使うべきです。
for(let i = 0; i < 100; i++) {
const value = i * 2;
console.log(value);
}
まとめ
- varは使わず、letとconstだけを使う。
- ほとんどの変数は再代入の必要が無いので、基本的にはconstを使う。
- どうしても再代入が必要なときだけletを使う。