こんにちは!フロントエンドの世界へようこそ。
JavaScriptを学び始めると、必ずと言っていいほど「あれ、なんでこうなるの?」と首をかしげたくなるポイントがありますよね。その代表格が、「forループの中で変数を使うとき、`var`と`let`で結果が違う問題」です。
今日は、この「JavaScriptの七不思議」の一つを、専門用語を抜きにして、身近な例え話でスッキリ解決していきましょう。大丈夫、最初は誰だってここで立ち止まるんです。一緒に紐解いていきましょう!
—
1. そもそも「変数」って何だろう?
プログラムにおける変数とは、「ラベルを貼った箱」のことです。
`var`と`let`は、どちらも「箱を作りますよ」という宣言なのですが、実はこの二人は「箱の管理の仕方」という性格が全く違います。
`var`は少しお節介な「共有大好き人間」。
`let`は一人ひとりのプライベートを大切にする「几帳面な整理整頓上手」。
この性格の違いが、forループという「繰り返し処理」の中で顕著に表れるんです。
—
2. varの「共有」という罠
まずは、よくある失敗例を見てみましょう。`var`を使ったforループです。
// 0秒後に、0, 1, 2 と表示したい!という願いを込めて
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // ここで何が表示されるかな?
}, 0);
}
// 実行結果:
// 3
// 3
// 3
「あれ? 0, 1, 2になるはずじゃなかったの?」と驚きますよね。
実はこれ、`var`が「ループ全体でたった一つの箱をみんなで使い回している」から起こる現象です。
例えるなら、「3人でお揃いの『i』という名前の付いた名札を、順番に付け替えている状態」です。
1回目に0だった名札は、2回目には1に書き換えられ、3回目には2に書き換えられ……最終的にループが終わったとき、その名札には「3」という数字が残っていますよね。
`setTimeout`(後で実行する命令)が動くときには、全員がその「最終的に3になった名札」を見てしまうので、結果がすべて「3」になってしまうんです。
—
3. letの「独立」という魔法
そこで登場するのが、ES6(JavaScriptの現代的な書き方)でやってきた`let`です。コードは一行変えるだけ。
// letを使ってみます
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 今度はどうなる?
}, 0);
}
// 実行結果:
// 0
// 1
// 2
見事、0, 1, 2 と表示されました!
なぜうまくいくのか? それは`let`が「ループが1回回るたびに、全く新しい箱を別々に用意してくれるから」です。
これは「お揃いの名札」ではなく、「その時その時の使い捨ての名札」を3人それぞれに渡しているイメージです。
1回目の箱には「0」、2回目の箱には「1」、3回目の箱には「2」がそれぞれ独立して保存されます。だから、後から見返したときも、ちゃんと自分の担当した数字を覚えていられるんですね。
—
4. 現場からのアドバイス
実務の現場では、もう`var`を使うことはほとんどありません。なぜなら、`var`の「どこからでも見えてしまう」「値を書き換えてしまう」という仕様は、大規模な開発になればなるほどバグの温床になってしまうからです。
今のJavaScript開発では、「基本は`let`か`const`(書き換えない変数)」を使うのが鉄則です。
覚えておいてほしいこと
- var: 古いJavaScriptの書き方。箱が共有されてしまうので、今はあまり使わない。
- let: 現代の標準。ブロック( `{ }` の中)ごとに箱を分けてくれるので、とっても安全。
- const: `let`と同じだけど、「一度決めたら変えないよ」という意思表示。迷ったらまずはこれでOK。
—
最後に
いかがでしたか? 「ループの中で値が全部同じになっちゃう!」という現象は、あなたが悪いわけではなく、JavaScriptの「変数の管理ルール」によるものだったんです。
この仕組みを理解できると、プログラムの裏側で何が起きているのかが少しだけ透けて見えてきます。その感覚が掴めれば、あなたはもう初心者から一歩先へ進んでいますよ!
また何か詰まったら、いつでも聞きに来てくださいね。あなたのエンジニアライフを応援しています!

コメント