Loading
  • LIGHT

  • DARK

ROUTE

ルートゼロの
アクティビティ

図解でわかる! JavaScript初心者がハマる letとvarの違いを徹底解説|現場での注意点まで完全対応

2

はじめに

「letとvarって結局どう違うの?」——多くの開発者が一度はこの疑問にぶつかります。ある日、varで書いたコードが思った通りに動かず、letに変えてみたら直った…でもその理由は分からない。

この記事では、“なんとなく使っている”状態から脱却し、JavaScriptの変数宣言に自信を持てるようになることを目指します。

letとvarを理解するメリット

  • 予期せぬバグを防げる

  • コードの可読性と保守性が向上する

  • モダンなJavaScriptの基礎が身につく

歴史的背景

JavaScriptが最初に登場した1995年当初、変数宣言に使えるのはvarのみでした。しかし、以下のような問題点が多く報告されていました:

  • グローバル汚染:varで宣言された変数はグローバルオブジェクト(windowなど)に追加されるため、意図せず既存の変数を上書きしてしまうことがある

  • スコープの曖昧さ:varは関数スコープであり、ブロックごとの制御ができない

  • ホイスティングによる予測困難なバグ:宣言だけが巻き上げられ、初期化が後になるためバグを生みやすい

これらの課題を解決するため、ES6(2015年)でletとconstが導入されました。これにより、ブロックスコープ一時的デッドゾーン(TDZ)など、より直感的で安全なコードを書く仕組みが整備されました。


varの特徴と挙動を理解する

varの主な特徴:

  • 関数スコープ

  • ホイスティング(巻き上げ)

  • 再宣言・再代入が可能

コード例:ホイスティングの罠

結論:宣言が巻き上げられ、初期化前にアクセスしてもエラーにならずundefinedになる

console.log(score); // 出力: undefined ← 変数scoreは宣言されているが、初期化前
var score = 10;     // 初期化はこのタイミング
実行イメージ:
var score;
console.log(score); // undefined
score = 10;
function test() {
  if (true) {
    var message = 'Hello'; // varは関数スコープに属する
  }
  console.log(message); // 出力: 'Hello' ← ブロック外でもアクセス可能
}
test();

letの特徴とモダンなJavaScriptでの役割

letの主な特徴:

  • ブロックスコープ

  • 一時的デッドゾーン(TDZ)

  • 再代入は可能だが、再宣言は不可

コード例:TDZの挙動

結論:宣言前にアクセスするとエラーになる(安全な挙動)

console.log(age); // ❌ ReferenceError: Cannot access 'age' before initialization
let age = 25;     // 初期化タイミング以降でなければアクセス不可
実行イメージ:
スコープ内に変数は存在しているが、初期化前のアクセスは禁止(TDZ)
function testLet() {
  if (true) {
    let greeting = 'Hi'; // このブロック内でのみ有効
  }
  console.log(greeting); // ❌ ReferenceError ← ブロックスコープの外なので参照不可
}
testLet();

実務で気をつけたい!varからlet/constへの移行ポイント

よくある落とし穴と注意点

forループ内のクロージャ

結論:letを使えば意図通りの値を保持できる

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
} // 出力: 3, 3, 3

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
} // 出力: 0, 1, 2

なぜこうなる?

  • varは関数スコープなので、ループ内で同じiを共有するため、ループ後の値が出力される

  • letはブロックスコープで、各ループごとに新しいiが定義されるため、想定通りの挙動になる

グローバル変数の扱い

結論:varはwindowオブジェクトに属し、let/constは属さない

var x = 10;
console.log(window.x); // 出力: 10 ← グローバルオブジェクトに属する

let y = 20;
console.log(window.y); // 出力: undefined ← windowのプロパティではない

なぜこうなる?

  • varで宣言した変数は、グローバルスコープであればwindowオブジェクトのプロパティとなる

  • letとconstはブロックスコープで、windowオブジェクトに紐付かない安全設計になっている


letとvarのおすすめ用途パターン(視覚ガイド)

┌──────────────┬────────────────────────────┐
│ 使用ケース     │ 推奨されるキーワード            │
├──────────────┼────────────────────────────┤
│ ループカウンタ    │ let(スコープ限定で安全)        │
│ 一度だけ使う値     │ const(再代入不可で意図が明確)   │
│ 古いコードの保守   │ var(無理に変えない方が安全な場合)│
│ 再代入が必要な変数 │ let(変更を許容する)            │
└──────────────┴────────────────────────────┘

constとの違いも軽くおさらい

constはletと同様にブロックスコープですが、再代入が不可であり、意図の明確化や安全性の向上に役立ちます。

const name = 'Alice';
name = 'Bob'; // ❌ TypeError
const user = { age: 25 };
user.age = 26; // ✅ OK(オブジェクトの中身は変更可能)

この記事で解決できるようになったこと

  • letとvarのスコープやホイスティングの違いを理解できた

  • TDZや再宣言不可の特性を把握し、安全な変数宣言ができるようになった

  • 実務での使い分けポイントと、移行時の注意点を学べた

  • constとの違いも簡潔に理解し、現代JSの変数宣言の全体像が見えた


まとめ

JavaScriptのletとvarの違いを理解することは、バグを減らし、コードを堅牢にする基礎力となります。

  • var:関数スコープ。古いコードやレガシー対応に限って使用。

  • let:ブロックスコープ。再代入が必要な場合に使う。

  • const:再代入不要な定数に使う。デフォルトの選択肢として推奨。

この違いを使いこなすことで、モダンJavaScriptの開発効率と安全性は格段に向上します。


【外部リンク】

MDN Web Docs – var

MDN Web Docs – let

MDN Web Docs – const

MDN Web Docs – 変数の使い方

【内部リンク】

JavaScriptでコードが書けない本当の理由と“順序設計”のすすめ
JavaScriptでよく発生するエラー「ReferenceError」「SyntaxError」などの原因と対策を具体例付きで解説
JavaScriptのAjax完全入門|fetchの使い方・CORSエラーの対処・非同期通信の基本を解説
JavaScriptの配列・JSON・map・Map:データ操作術
TypeError: Cannot read propertyの意味と回避術【初心者向け】

RANKINGranking-icon

LATEST POSTS

もっとルートゼロを知りたいなら

DISCOVER MORE