まず結論:「新しく書くコードでは var はほぼ使わない」
JavaScript には変数宣言が 3 種類あります。
var
let
const
JavaScript昔の JavaScript には var しかありませんでした。
その後、「危ない挙動が多すぎる」という反省から、
より安全で直感的な let / const が追加されました。
ここが重要です。
今から JavaScript を学ぶ人は、「変数は let / const を使う。var は“古い書き方”として基本使わない」
と考えて問題ありません。
では、なぜ var を使わないほうがいいのか、具体的な「怖さ」をかみ砕いて説明します。
理由1:var は「ブロックの中だけ」に閉じてくれない(スコープが広すぎる)
let / const は「{ } の中だけ」で有効
let / const は ブロックスコープ です。
つまり、{ } の中で宣言した変数は、その { } の中だけで有効です。
if (true) {
let x = 10;
console.log(x); // 10(ここでは使える)
}
console.log(x); // エラー:x は定義されていない
JavaScriptこれは直感的ですよね。
「この if の中だけで使いたい変数」は、外から触れないほうが安全です。
var は「関数スコープ」なので、ブロックを無視する
var は 関数スコープ です。if や for の { } を「スコープ」として見てくれません。
if (true) {
var y = 10;
console.log(y); // 10
}
console.log(y); // 10 (えっ…? ここでも見える)
JavaScriptif の中で宣言したはずの y が、
if の外でも普通に見えてしまいます。
もう少しハマりやすい例を出します。
for (var i = 0; i < 3; i++) {
console.log("ループ内:", i);
}
console.log("ループ外:", i); // 3(i が外にも漏れている)
JavaScript「ループのカウンター i」のつもりが、
関数の外(最悪グローバル)にまで生き続けてしまう ことがあります。
let を使った場合はこうです。
for (let i = 0; i < 3; i++) {
console.log("ループ内:", i);
}
console.log("ループ外:", i); // エラー:i は定義されていない
JavaScript直感どおり、「ループ専用の変数」として振る舞ってくれます。
ここが重要です。
var は「意図せず外側に変数が漏れる」リスクが高い。
スコープがゆるすぎて、変数名の衝突や上書きバグを招きやすい。
だから、ブロックスコープな let / const のほうが安全です。
理由2:var は「同じ名前で何度でも宣言できてしまう」(上書き事故の温床)
let / const は「二重宣言」を防いでくれる
let x = 1;
let x = 2; // エラー:「x はすでに宣言されています」
JavaScript同じスコープで同じ名前の変数を宣言しようとするとエラーになります。
これは「うっかり上書きを防ぐ安全装置」です。
var は二重宣言しても怒らない
var y = 1;
var y = 2; // エラーにならない
console.log(y); // 2
JavaScriptサイレントに上書きされます。
小さいスクリプトならまだしも、
ファイルが大きくなったり、複数人で開発していると、
「自分が別の場所で同じ名前をもう使っていた」
「ライブラリの中でもその名前が使われていた」
といったことが起きやすく、
意図しない上書き が発生しやすくなります。
ここが重要です。
let / const は「その名前、もう使ってるよ」と教えてくれるが、var は黙って上書きしてしまう。
見つけにくいバグに直結するので、わざわざ var を選ぶ理由はほとんどありません。
理由3:var の「巻き上げ(ホイスティング)」が直感に反する
var は「宣言だけ上に持ち上がる」という挙動をする
次のコードを見てください。
console.log(a); // undefined(エラーではない)
var a = 10;
console.log(a); // 10
JavaScript一見、「宣言前に使ってるからエラーになりそう」ですが、var ではエラーになりません。
これは JavaScript の「ホイスティング」という仕様で、
内部的にはこう解釈されています。
var a; // 宣言だけ先頭に“巻き上げ”られる
console.log(a); // undefined
a = 10;
console.log(a); // 10
JavaScriptつまり、「宣言だけ先に行われ、代入は元の位置で行われる」 という挙動です。
let / const は「宣言前に使うとちゃんとエラー」
console.log(b); // エラー:参照できない
let b = 10;
JavaScriptlet / const にもホイスティング自体は起きているのですが、
「宣言前にアクセスするとエラーになる」という、
より安全な挙動 になっています(TDZ:Temporal Dead Zone)。
ここが重要です。
var のホイスティング挙動は、“後から宣言したのに前で使えてしまう”状態を作り、
コードの見た目と実際の実行順序のギャップを生みます。
初心者にとっては完全に罠なので、そもそも var に近づかないほうが安全です。
理由4:「for ループ × var」で有名なバグパターンが生まれる
典型的な罠の例
次のコードを見てください。
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 100);
}
JavaScript「0, 1, 2 が表示されるかな?」と思うかもしれませんが、
実際の出力はこうなります。
3
3
3
理由は、
var i がブロックスコープではなく、
ループ全体で「1 つの i」を共有しているからです。
タイマーが実行される頃にはループが終わっていて、i はすでに 3 になっているため、
どのコールバックから見ても i === 3 になってしまいます。
let なら直感どおりに動く
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 100);
}
JavaScriptこの場合はちゃんと、
0
1
2
と表示されます。
let はブロックスコープなので、
各ループごとに“別々の i” が存在する と考えられます。
ここが重要です。
「ループの中で非同期処理を使う」ときに、var は直感とずれた振る舞いをしがち。
let を使えば、このよくあるバグパターンを自然と避けられます。
理由5:グローバル汚染の危険性が高い
var は「うっかりグローバル変数」を作りやすい
ブラウザ環境では、グローバルオブジェクト(window)に直接プロパティを追加するような形で、
変数が定義されることがあります。
var でグローバルに宣言すると:
var foo = 123;
console.log(window.foo); // 123(ブラウザの場合)
JavaScriptつまり、「グローバル名前空間」を汚染しやすい のです。
古いコードやライブラリがたくさん var を使っていると、
「どこで定義されたか分からないグローバル変数」が増え、
名前の衝突や予期せぬ上書きが起こりやすくなります。
let / const はグローバルに置いても window に乗らない(ブラウザの場合)
let bar = 456;
console.log(window.bar); // undefined
JavaScriptlet / const はグローバルに書いても、window のプロパティにはなりません(仕様上の違い)。
ここが重要です。
var は「グローバル汚染」「名前衝突」の危険性を高める。
大きなプロジェクトになればなるほど、var でのグローバル変数は地雷原になります。
それでも var を「知っておく」理由
古いコード・教材・記事に出てくる
「新しく書くコードでは var を使わない」
これはほとんどの現場で共通の方針です。
ただし、
- 古い本・記事・ブログ
- 古いライブラリのコード
- 既存のレガシーなプロジェクト
では、いまだに var が大量に出てきます。
そのときに、
「なんか昔の書き方らしい」
「スコープがゆるい/ホイスティングするらしい」
というのを知っているだけで、
読んだときの理解が全然違ってきます。
「使わない」ためにも、ざっくり特徴だけは知る
ここまでの話を超ざっくりまとめると、
varは- 関数スコープ(ブロックスコープではない)
- 宣言の重複OK(上書き事故の元)
- ホイスティングで宣言前に参照できてしまう(undefined)
- for ループ+非同期でバグパターンの温床
- グローバル汚染しやすい
- 対して
let/constは- ブロックスコープで直感的
- 二重宣言を防ぐ
- 宣言前アクセスはエラー(安全)
という関係です。
ここが重要です。
「var はこういう危ない挙動をするから、今は使わない」という理由を知っておくことで、
古いコードを読むときに「なぜここでバグが起きているか」を理解しやすくなります。
まとめ:「var を使わない理由」を初心者目線で言い直すと
最後に、初心者向けに言い直すとこうです。
var は、昔 JavaScript にしかなかった変数の書き方。
でも、
- ブロックの外にまで変数が漏れたり
- 同じ名前で何度も宣言できたり
- 宣言前に使えてしまったり(undefined)
と、「人間の直感とズレる」「バグの元になる」挙動が多い。
その反省から、
振る舞いが素直で安全な let / const が後から用意された。
だから、今から JavaScript を書く人は、
「変数は let / const を使う。var は“古い危ない書き方”として読めれば十分」
というスタンスでいるのがベスト。
ここが本当に重要です。
あなたが「var を使わない」と決めること自体が、JavaScript で変なバグに巻き込まれないための一番簡単な防御策です。
もし余裕があれば、
小さなファイルを作って
varとletを if や for の中で試してみる- 宣言より前で
console.logしてみる
など、「実際に var の気持ち悪さ」を自分の目で確認してみてください。
一度体感すると、「ああ、これは確かに使いたくないな」と、腹の底から実感できるはずです。
