JavaScriptの変数宣言(var・let・const)の違い【それぞれの役割とは?】
フロントエンドでもバックエンドでも広く使われるJavaScriptでは、値を入れておく変数の取りあつかいが安定したコードの土台です。とくにES6から追加されたletとconstの登場で、「いつ」「どこで」「どんなふうに」使い分けるかは学びたての方がまずつまずく所でもあります。
この記事では従来のvarと合わせて三つの宣言方法を比べ、スコープや再宣言の可否、ホイスティングの動きなどを具体例つきでやさしく整理します。これを読めばプロジェクトのバグを未然に防ぎ、読みやすいコードへ一歩前進できます。
var・let・const の基本・違い
スコープ:関数スコープ と ブロックスコープ
varで作られた変数は関数スコープです。関数の中で宣言すれば外から見えず、関数外で宣言すればグローバルになります。それに対し、letとconstはブロックスコープなので { }
で囲まれた部分だけで有効です。たとえばforループの中でカウンタをlet宣言すればループが終わったら消え、思わぬ値上書きを防ぎやすくなります。
なお、グローバルスコープで var
によって宣言された変数は、ブラウザ環境では window
オブジェクトのプロパティとして登録されますが、let
や const
ではグローバルオブジェクトへの登録は行われません。
// var はブロックをまたいで有効
if (true) {
var x = 1;
let y = 2;
}
console.log(x); // 1 と表示される
console.log(y); // ReferenceError: y is not defined
再宣言・再代入:エラー回避のポイント
varは同じスコープで再宣言も再代入も許可されます。便利な反面、うっかり同名変数を上書きしてバグの火種になる事も多いです。
letは同じスコープでの再宣言は不可ですが再代入は可能です。型や内容が変わる可能性がある値に向いています。
constは再宣言も再代入も不可で、値を固定したい設定情報などに適します。ただしオブジェクトや配列の中身は変えられるため、「定数=完全不変」というわけではない点に注意しましょう。
ホイスティング と Temporal Dead Zone
三つとも宣言は巻き上げ(ホイスティング)されます。しかし挙動が異なります。varは宣言が先に評価されundefinedで初期化された状態から読めます。
一方、letとconstは宣言前にアクセスするとReferenceErrorを出すTemporal Dead Zoneに入ります。「先に書いたつもりだけど実は読み込みが早かった」というバグを検出しやすく設計されているのが特徴です。
実例で学ぶ var の特徴とリスク
下記コードではforループのあとにvar iを読むと最後のカウント値が見えます。この動きは一見便利ですが、関数が増えると想定外の上書きが連鎖しやすくなります。
モダン開発ではレガシーAPIや古いブラウザ互換が必要な場合を除き、varの新規利用は最小限にとどめるのが一般的です。既存コードに手を入れる際は、まずグローバル汚染や二重宣言が無いか静的解析ツールでチェックしてからリファクタリングを進めると安全でしょう。
実例で学ぶ let の柔軟性と安全性
letはブロック内限定で書き換えも可能なため、多段ループや条件分岐で状態が変動する処理に向きます。たとえば非同期処理で for (let i = 0; i < list.length; i++)
とし、内部で await fetch(...)
を呼んでもクロージャが正しい i
を保持します。
これはvar時代の「ループ後 callback が全部同じ値問題」を根本から解消します。コードレビュー時には「スコープが意図どおりか」「再代入される妥当な理由があるか」を確認すると品質が向上します。
実例で学ぶ const の安心感とベストプラクティス
constは読み取り専用の参照を作るイメージです。なお、const
宣言では必ず初期化子(=
による値の指定)が必要で、省略すると構文エラーになります。プリミティブ型なら値そのものが固定されますが、配列やオブジェクトは要素の追加やプロパティ変更が可能です。
たとえば const settings = {theme: "light"}
とした後で settings.theme = "dark"
は正しく動きます。設定オブジェクトを完全に凍結したい場面では Object.freeze
を組み合わせましょう。
チーム開発では「まずconst、必要ならlet、原則varは使わない」という順で宣言し、定義の意図をコードに刻むのが主流になっています。
よくある疑問 と FAQ
- var はもう使わなくていいですか?
-
古いブラウザ対応で互換性を優先する場合や、既存大量コードとの統一が必要な場合のみ使用します。それ以外はlet / constが推奨です。
- const でもオブジェクトのプロパティを書き換えて良い?
-
書き換えは可能ですが、設定値を完全固定したいなら freeze を使うか、deepFreezeユーティリティを導入しましょう。
- パフォーマンスに差はありますか?
-
現行エンジンではスコープ解決コストの違いは無視できる程度です。読みやすさやバグ防止を優先してください。
まとめ:シーン別 最適な宣言の選び方
三つの宣言方法を整理すると、varは互換確保が主目的、letは状態が変わるブロックローカル変数、constは変更しない参照に向きます。チームポリシーとして「デフォルトconst、変動時のみlet」を採用すればコードの意図が読み取りやすくなり、レビュー効率も向上します。
自動フォーマッタやリンターにルールを設定し、CIで違反を検出するとさらに安心です。今回のポイントを押さえ、日々の実装で適切な宣言を選べば、予期しないバグを遠ざけて未来の自分や仲間へ親切なコードベースを築けるでしょう。