JavaScriptで変数を扱うときのvarとletとconstの違い

Web制作でよく利用されるプログラミング言語、JavaScriptの変数には基本的な変数宣言のvarの他、ECMAScript2015以降の仕様から利用可能なletやconstなどがあります。JavaScriptも構文がアップデートされてどんどん強力になってきました。

Google Chrome、Firefox、Safari、Edge、Internet Explorerといった主要ブラウザもECMAScriptに対応してきて多くのWebブラウザで実装できます。
ただ、Internet ExplorerだけIE10を含むIE10以前のブラウザは残念ながら対応していません。Microsoft社も企業にInternet Explorerの使用をやめるよう要請しているのでこれからはあまり気にすることはないと思います。古いWebブラウザを無視すればletとconstを利用してプログラムを書いていくことができます。

変数の宣言方法が増えたわけですがどのような違いがあるのか、また何が便利になったのかまだ理解されていない方のために変数の扱いについていろいろ説明していこうと思います。


varとletとconstの違い


まずはvarとletとconstの違いを見てみましょう。

var
基本的な変数宣言。

let
ECMAScript2015以降で使える新しい変数宣言で、ブロックスコープとなる。
変数の値の再代入が可能です。

const
ECMAScript2015以降で使える新しい変数宣言で、ブロックスコープとなる。
一度宣言すると値の再代入はできません。プログラミング言語の「final」と同じ扱いになる。

ざっくり言うとletとconstはブロックスコープ認識の変数でletは再代入可能、constは再代入できず定数のような扱いといった感じです。


気になるのは新しい変数の便利さです。
どのような便利さなのかを少しサンプルを交えて説明します。


変数の重複を防ぐ

varで変数宣言をすると、プログラムを書いていく中で変数名を重複させてしまった時に変数の値の上書き前のプログラムが壊れるといったことが起こる可能性があります。
しかしletで変数宣言をすることで、もし同じ名前で変数宣言してしまったとしてもエラーとなり早めに重複に気づくので、他のプログラムのバグが発生しにくくなります。

var hoge = "変数1";
var hoge = "変数2";

console.log(hoge); // 変数2(変数は上書きされる)

let hogehoge = "変数1";
// let hogehoge = "変数2"; <= 重複するとエラーになる
hogehoge = "変数3"
console.log(hogehoge); // 変数3を出力


letと利用した方が安全に開発を進めることができます。


ブロックスコープの認識の違い


PHPやJavaではブロックレベルのスコープが存在しますが、JavaScriptではブロックレベルのスコープが存在しません。
従来のvarで変数の宣言をするとグローバル変数にもローカル変数にもなります。

例えば、if文のブロックで見てみましょう。

まずはvarの場合。

var i = 1;
if (true) {
  var i = 2;
  var j = 3;
}
console.log(i); // 2と出力
console.log(j); // 3と出力


varでは、if文の外で宣言した変数と値に対してif文の中で再代入させても、if文を抜けたブロックの外ではブロックの中で再代入した値が出力されます。
プログラムによってはこれがちょっとしたバグの原因を作ることもあります。


続いてletの場合。

let n = 1;
if (true) {
  let n = 2;
  let m = 3;
  console.log(n); // ブロックの中の変数n「2」と出力
}
console.log(n); // ブロックの外の変数nの「1」と出力
console.log(m); // 変数「m」の宣言がなくエラーとなる


letでは、ブロックの外で宣言した変数に対してブロック内で同じ変数名「n」で宣言して重複させてもブロックレベルのスコープの認識なのでブロック内の変数nとなります。
ブロック内で宣言した変数「m」はブロックレベルのスコープのためブロックの外では無効です。変数mが宣言されていないというエラーが返ってきます。

letの方が変数の扱いを細かく管理できるので、条件分岐や関数といったプログラムを多用していく中でグローバル変数とローカル変数の扱いがはっきりしていて開発しやすくなります。


constも同じです。

const t1 = "定数1";
if (true) {
  const t1 = "定数2"; // ブロックスコープなので重複ではない
  const t2 = "定数3";
  console.log(t1); // 定数2を出力
}
console.log(t1); // 定数1を出力
console.log(t2); // 定数「t2」の宣言がなくエラーとなる


constもlet同様、ブロックレベルのスコープの認識なのでブロック内で宣言した「t1」は重複にはなりません。
もちろんブロック内で宣言した「t2」はブロックの外で利用しようとしてもエラーとなります。


まとめ


JavaScriptのECMAScript2015以降の仕様からは、varよりletを利用することで変数をより安全に細かく扱うことができるようになったこと、そしてconstでより簡単にブロックレベルで定数を扱えるようになったこと。まだまだ氷山の一角ですがいろいろと強力になりました。

これからはletやconstを利用したいったほうが安全で快適な開発を行うことができます。

一応最後にもう一度言っておきますが、IE10以前の古いWebブラウザは対応していないことも忘れずに。これからの時代はあまり気にすることもないと思いますが。
Internet Explorer10以前のブラウザの利用も気にするようでしたら基本的なvarでの変数宣言を利用していただければと思います。その場合は宣言の重複やブロックレベルのスコープの認識が無いことに気にかけながらプログラムを書いていってください。