JavaScriptのスコープとは?ローカル変数・グローバル変数の違いと使い分け
生徒
「JavaScriptで変数を作ってみたんですが、場所によって動かないことがあります。なんでですか?」
先生
「それは『スコープ』という仕組みに関係しています。スコープとは、変数が使える範囲のことなんです。」
生徒
「変数が使える範囲?それってどういうことですか?」
先生
「よし、それではJavaScriptのスコープについて、やさしく説明していきましょう!」
1. JavaScriptのスコープとは?
JavaScriptのスコープ(Scope)とは、一言でいうと「その変数がどこまで有効か?」という有効範囲のことです。プログラムの中で宣言した変数は、どこでも自由に読み書きできるわけではなく、実はそれぞれ「活動できる限界の境界線」が決まっています。
もしスコープという仕組みがなかったら、プログラムのあちこちで同じ名前の変数がぶつかり合い、予期せぬ場所で値が書き換わってしまうといったバグ(不具合)が多発してしまいます。初心者の方が「変数を定義したはずなのに動かない!」と悩む原因の多くは、このスコープの外側から変数にアクセスしようとしているケースです。
JavaScriptのスコープは、大きく分けて以下の2つのレベルで考えると理解がスムーズです。
- グローバルスコープ:プログラムのどこからでもアクセスできる「公共の広場」のような範囲
- ローカルスコープ:関数やブロックの中など、限られた場所でしか使えない「個室」のような範囲
例えば、家全体で使える「テレビのリモコン」がグローバル変数だとすれば、自分の部屋の机の引き出しにしまってある「自分専用のノート」がローカル変数、といったイメージです。
未経験者向けのシンプル例:
let globalName = "世界中の人"; // グローバルスコープ(どこでもOK)
function sampleFunction() {
let localName = "部屋の中の人"; // ローカルスコープ(この関数内だけ)
console.log(globalName); // 表示できる
console.log(localName); // 表示できる
}
sampleFunction();
console.log(localName); // 【エラー!】部屋の外からは見えません
世界中の人
部屋の中の人
Uncaught ReferenceError: localName is not defined
このように、「変数の見える範囲を適切に制限すること」が、安全で読みやすいコードを書くための第一歩となります。
2. グローバル変数とは?
JavaScriptを学び始めたばかりの方が最初につまずきやすいのが、「変数の使える範囲(スコープ)」です。その中でも、グローバル変数は「プログラムのどこからでも自由にアクセスできる変数」のことを指します。
たとえば、家の中に置いてある「家族全員で使うテレビ」のようなイメージです。リビングにあっても、寝室から見に来ても、どこからでも使うことができますよね。プログラミングでは、関数の外側(一番外側の階層)で変数を宣言すると、それが自動的にグローバル変数になります。
// 関数の外側で宣言した「グローバル変数」
let message = "こんにちは!グローバル変数の世界へようこそ。";
function greet() {
// 関数の中から外側の変数を見に行くことができる
console.log(message);
}
// 関数を実行
greet();
こんにちは!グローバル変数の世界へようこそ。
このサンプルコードでは、messageという変数が関数の外にあります。そのため、greetという関数の中からでも、その中身を読み取って表示させることが可能です。このように、場所を問わずどこからでも呼び出せるのがグローバル変数の最大の特徴です。
初心者の方は、まず「外側で作った変数は、内側の関数の中でも使えるんだな」という基本ルールを覚えておきましょう。ただし、どこからでも中身を書き換えられてしまうという性質もあるため、大規模な開発では注意が必要になりますが、まずはこの「共有の棚」のような仕組みを理解することが大切です。
3. ローカル変数とは?有効範囲(スコープ)を初心者向けに解説
ローカル変数とは、プログラムの中の「特定の範囲(関数やブロックなど)」だけで利用できる限定的な変数のことです。この変数が使える有効範囲のことを、プログラミング用語で「スコープ」と呼びます。
例えば、料理のレシピで「隠し味」をその料理の中だけで使うように、関数の中で宣言した変数は、その外側から中身を覗いたり、書き換えたりすることはできません。これにより、他の場所で使っている変数名と名前が重なっても影響を受けないという大きなメリットがあります。
ローカル変数の具体例とエラーの仕組み
以下のサンプルコードで、関数の中と外でどのように動作が変わるか見てみましょう。JavaScriptのletやconstを使って関数内で宣言すると、それは自動的にローカル変数になります。
function greet() {
// 関数の中で宣言した「message」はローカル変数
let message = "こんにちは!";
console.log("関数の中での実行結果:");
console.log(message);
}
// 関数の実行
greet();
// 関数の外でローカル変数を使おうとすると…?
console.log("関数の外での実行結果:");
console.log(message); // ここでエラーが発生します
実行結果:
関数の中での実行結果:
こんにちは!
Uncaught ReferenceError: message is not defined
このコードを実行すると、最初のgreet()の中では正しくメッセージが表示されますが、最後の行ではmessage is not defined(messageなんて定義されていませんよ)というエラーが表示されます。これは、messageという変数がgreet関数の「壁」に守られており、外側からは存在すら見えない状態になっているためです。
このように、ローカル変数を活用することで、「この変数はこの処理だけで使う」という区別が明確になり、大規模なプログラムでもバグを防ぎやすくなります。
4. ブロックスコープ:より安全な変数管理の仕組み
これまでは「関数」の内か外かで変数の有効範囲が決まっていましたが、実はもっと身近な「ブロック(波かっこ { } で囲まれた範囲)」にもスコープが存在します。これをブロックスコープと呼びます。
現代のJavaScript(ES6以降)において、letやconstを使って宣言された変数は、すべてこのブロックスコープに従います。例えば、if文やfor文の中で宣言した変数は、その外側からは一切見ることができません。
初心者向けの例え:
ブロックスコープは「個室」のようなものです。部屋({ })の中で用意した道具(変数)は、その部屋を出ると消えてしまう、あるいは外からは使えない決まりになっています。これにより、うっかり他の場所で同じ名前の変数を使ってしまっても、中身が混ざり合う心配がありません。
if (true) {
// ここからブロックスコープの開始
let message = "秘密のメッセージ";
console.log(message); // 結果:秘密のメッセージ
// ここまででブロックスコープが終了
}
// ブロックの外からアクセスしようとすると...
console.log(message);
実行結果は以下のようになります。
秘密のメッセージ
Uncaught ReferenceError: message is not defined
このように、エラーが出るのは「変数がそのブロックの中だけで守られている証拠」です。この仕組みがあるおかげで、大規模なプログラムを作るときでも、変数の衝突を防ぎ、バグの少ない安全なコードを書くことができるようになります。プログラミング未経験の方は、まずは「{ } の外では let や const は使えなくなる」と覚えておけば完璧です。
5. 昔の書き方「var」との違いと注意点
JavaScriptの学習を進めると、letやconstのほかにvarというキーワードを目にすることがあります。これは古いJavaScriptで主流だった書き方ですが、現代のプログラミングでは、ある「困った特徴」があるため、ほとんど使われません。
一番の違いは、「変数が有効な範囲(スコープ)」にあります。letは { }(ブロック)の中でしか使えませんが、varはブロックを無視して外側からも読み取れてしまいます。
初心者でもわかる!varの挙動サンプル
例えば、プログラミング未経験の方が間違いやすい「箱(変数)のルール」を比較してみましょう。varを使うと、本来その場だけで使い切りたかったデータが、外に漏れ出してしまいます。
if (true) {
var message = "こんにちは!"; // varで宣言
}
// 本来ならifの中だけで有効なはずが、外で使えてしまう
console.log(message);
実行結果は以下のようになります。
こんにちは!
「外で使えるなら便利じゃないか」と思うかもしれませんが、これが「思わぬバグ」の特大の種になります。大規模なプログラムになると、どこで誰が作った変数かわからなくなり、中身が勝手に書き換わってしまうリスクがあるからです。
結論: 2026年現在の開発現場では、「変数はlet、定数はconst」を使うのが鉄則です。varは「昔はこう書いていたんだな」と理解しておく程度で問題ありません。
6. グローバル変数はなるべく使わない
グローバル変数は便利に見えますが、プログラムが大きくなると「どこで変えられたのか分からなくなる」ことがあります。そのため、なるべく関数の中だけで使うローカル変数を使うようにしましょう。
もし複数の関数で同じ値を使いたい場合は、引数(関数に渡す値)として受け渡すのが安全です。
7. スコープの例:お弁当箱に例えてみよう
スコープをお弁当箱にたとえると分かりやすいです。
- ローカル変数 = 自分のお弁当箱の中に入っているおかず(他の人は食べられない)
- グローバル変数 = みんなで食べるお弁当(誰でも取れるけど、誰が食べたか分からなくなる)
つまり、なるべく自分の弁当箱の中だけでやりくりしたほうが安全ということです。
8. スコープチェーンとは?
JavaScriptでは、ローカル変数が見つからないと、ひとつ外側のスコープを順に探していきます。これをスコープチェーンといいます。
let greeting = "こんにちは";
function sayHello() {
console.log(greeting);
}
sayHello(); // こんにちはと表示される
sayHello関数の中にはgreetingがありませんが、外側にあるグローバル変数のgreetingを見つけて表示します。
まとめ
ここまでJavaScriptのスコープについて、その基礎から応用、そして注意点まで詳しく解説してきました。変数がどこで使えて、どこで消えてしまうのかというルールを理解することは、プログラムが正しく動くための「地図」を手に入れるようなものです。
スコープの重要性を再確認
プログラミング初心者の方が最初につまずきやすいのが、「さっきまで動いていた変数が、別の場所ではエラーになる」という現象です。この記事で学んだ通り、それはバグではなく、JavaScriptが提供してくれている「変数の衝突を防ぐための仕組み」なのです。
もし、すべての変数がどこからでも自由に書き換えられる「グローバル変数」ばかりの世界だったら、開発現場は大混乱に陥ります。ある場所で数字を計算している最中に、別の場所から勝手にその数字を文字列に変えられてしまう、といった予期せぬトラブルが多発するからです。だからこそ、「必要な場所だけで使い、使い終わったら捨てる」というローカルスコープの考え方が非常に大切になります。
適切なキーワードの選び方
現代のJavaScript(ES6以降)において、変数の宣言は let と const が基本です。
特に、一度代入したら中身を変えない定数 const をメインで使い、どうしても再代入が必要な場合だけ let を使うようにすると、スコープの管理がさらに楽になります。
古いコードで見かける var は、ブロックスコープを無視してしまうため、現代の開発では推奨されません。これから学習を始める方は、まずは let と const を使いこなし、自分が必要な範囲(関数内やif文の中など)に限定して変数を定義する癖をつけていきましょう。
実践的なサンプルコードで復習
実際に、複数のスコープが混在するプログラムで、変数がどのように扱われるかを復習してみましょう。下記のコードは、グローバル変数、ローカル変数(関数スコープ)、そしてブロックスコープがどのように共存するかを示しています。
// 1. グローバルスコープ:どこからでもアクセス可能
const appName = "スコープ学習アプリ";
function checkScope() {
// 2. 関数スコープ(ローカル変数):この関数の中だけで有効
let status = "実行中";
if (true) {
// 3. ブロックスコープ:このif文の{ }の中だけで有効
let blockMessage = "if文の中です";
const tempId = 12345;
console.log(appName); // アクセス可能(グローバル)
console.log(status); // アクセス可能(外側の関数スコープ)
console.log(blockMessage); // アクセス可能(現在のブロック)
}
// ここでblockMessageを呼び出すとエラーになります
// console.log(blockMessage);
console.log(status); // アクセス可能
}
checkScope();
上記のコードの実行結果は、コンソールに以下のように出力されます。
スコープ学習アプリ
実行中
if文の中です
実行中
このように、内側のスコープから外側のスコープにある変数を参照することはできますが、その逆はできません。これを「情報の隠蔽(カプセル化)」の第一歩として意識できると、エンジニアとしてのスキルがぐっと向上します。
今後の学習に向けて
スコープの概念に慣れてくると、「クロージャ」というさらに高度なJavaScriptの機能も理解しやすくなります。まずは、自分が書いている変数が「今、どこの波かっこの中にいるのか?」を常に意識することから始めてみてください。
安全で読みやすいコードを書くためには、「グローバル変数を最小限にする」という鉄則を忘れないようにしましょう。プログラムが大きくなればなるほど、この小さな習慣が大きな差となって現れてきます。
生徒
「先生、ありがとうございました!スコープの意味がようやく分かりました。変数がどこまで生きているか、という寿命のようなものなんですね。」
先生
「その通りです!よく理解できましたね。特にJavaScriptでは、波かっこ { } が一つの境界線になっていることが多いんですよ。これを意識するだけで、エラーの探し方も変わってきます。」
生徒
「今までは何でも関数の外で let を使って書いてしまっていましたが、それだと他の場所で同じ名前を使った時に混乱しちゃいますね。これからは、できるだけ if 文や function の中で宣言するようにします!」
先生
「素晴らしい心がけです。ちなみに、なぜ var ではなく let や const を使ったほうがいいのか、その理由はもう一度言えますか?」
生徒
「はい! var はブロックを突き抜けてしまうからですよね。 if 文の中で作ったはずなのに外で使えてしまうのは、規模が大きな開発だと怖いなって思いました。 let なら、ちゃんとブロックの中に閉じ込めておけるから安心です。」
先生
「満点です。プログラミングは自由度が高い分、自分たちでルールを作って守ることが大切です。スコープはそのルールの基礎中の基礎。これをマスターした君なら、もっと複雑なアプリ開発にも挑戦できますよ!」
生徒
「ありがとうございます!なんだかワクワクしてきました。次は、このスコープを活かして、もっと綺麗なコードが書けるように練習してみます!」