2026年4月16日
JavaScript スコープとは?
「変数を作ったのに使えない」「どこからでも変数を使えると思っていたのに…」——こんな経験はありませんか?
スコープ(scope)とは「変数が使える範囲」のことです。JavaScript スコープを理解すると、変数がどこで使えてどこで使えないかがわかります。スコープを理解していないと、「変数が見つからない」「意図しない値が入っている」といったバグに悩まされます。
この記事では、グローバルスコープ・ローカルスコープ・ブロックスコープの3種類を、コード例を使ってわかりやすく解説します。クロージャやvar/let/constの違いも説明するので、スコープに関する疑問がすべて解決します。
グローバルスコープ:どこからでも使える
関数や の外で宣言した変数は グローバルスコープ を持ち、プログラムのどこからでも使えます。
const siteName = 'プログラミング入門'; // グローバル変数
function greet() {
console.log(siteName); // 関数の中からも使える
}
greet(); // プログラミング入門
🔗 あわせて文字列操作入門もチェックしてみましょう。
ローカルスコープ:関数の中だけで使える
関数の中で宣言した変数は ローカルスコープ を持ち、その関数の中だけで使えます。
function greet() {
const message = 'こんにちは!'; // ローカル変数
console.log(message); // OK
}
greet();
// console.log(message); // エラー!関数の外からは使えない
ブロックスコープ:{}の中だけで使える
let と const は ブロックスコープ を持ちます。 の中で宣言した変数は、その の中だけで使えます。
if (true) {
const x = 10; // ブロックスコープ
console.log(x); // 10
}
// console.log(x); // エラー!ブロックの外からは使えない
for (let i = 0; i < 3; i++) {
// i はforブロックの中だけで使える
}
// console.log(i); // エラー!
📖 詳しくはPromise入門で解説しています。
varはブロックスコープを持たない(注意)
var はブロックスコープを持たないため、 の外からでも使えてしまいます。これがバグの原因になりやすいため、現在は let・const を使うことが推奨されています。
if (true) {
var y = 20; // varはブロックスコープなし
}
console.log(y); // 20(ブロック外でも使えてしまう)
👉 変数の基本も参考にしてください。
クロージャ(Closure)
関数の中で定義された関数が、外側の関数の変数にアクセスできる仕組みをクロージャと呼びます。スコープの応用です。
function createCounter() {
let count = 0; // 外側の関数の変数
return function() {
count++; // 内側の関数から外側の変数にアクセス
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
count は createCounter の中で定義されていますが、返された関数からアクセスし続けられます。これがクロージャです。
よくある間違い
- varのスコープを誤解する:
varはブロックスコープを持たないため、if文やfor文の中で宣言しても外からアクセスできてしまいます。常にlet/constを使いましょう。 - グローバル変数の多用:グローバルスコープに変数を置きすぎると、名前の衝突やバグの原因になります。変数はできるだけ狭いスコープで宣言しましょう。
📖 エラーハンドリング入門でデバッグ方法を学べます。
🔗 JavaScript入門で基礎を確認できます。
let / const / var の使い分け
const:再代入しない変数(基本これを使う)。配列やオブジェクトの中身は変更できますが、変数自体への再代入はできません。let:再代入する変数。ループのカウンターや、後から値が変わる変数に使います。var:使わない(レガシー)。ブロックスコープがなく、巻き上げの挙動もわかりにくいため、新しいコードでは使いません。
迷ったらまず const で宣言し、再代入が必要になったら let に変えましょう。この習慣をつけると、意図しない値の変更を防げます。
スコープに関するよくあるバグ
ループ内のvarで意図しない値になる問題
// NG: varはブロックスコープがないため、iが共有される
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 3, 3, 3(全部3になる!)
}, 100);
}
// OK: letはブロックスコープがあるため、各ループで別のiになる
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 0, 1, 2(期待通り)
}, 100);
}
この問題は面接でもよく聞かれる有名なバグです。let を使えば簡単に解決できます。
グローバル変数の汚染
グローバルスコープに変数を置きすぎると、別のスクリプトと名前が衝突してバグの原因になります。変数はできるだけ関数やブロックの中で宣言しましょう。
巻き上げ(hoisting)の挙動
var で宣言した変数は、宣言部分がスコープの先頭に「巻き上げ」られます。ただし値の代入は巻き上げられません。
console.log(x); // undefined(エラーにならない!)
var x = 10;
// letの場合はエラーになる(安全)
// console.log(y); // ReferenceError
// let y = 10;
🔗 変数の基本・関数とスコープ・JavaScript入門・ループ・アロー関数とthisも参考にしてください。
実践例:モジュールパターン
スコープを活用した「モジュールパターン」は、変数を外部から隠蔽する実践的なテクニックです。関数スコープを使って、外部からアクセスできないプライベートな変数を作れます。
const calculator = (function() {
let history = []; // 外部からアクセスできない
return {
add(a, b) {
const result = a + b;
history.push(result);
return result;
},
getHistory() {
return [...history];
}
};
})();
calculator.add(2, 3); // 5
console.log(calculator.getHistory()); // [5]
// console.log(calculator.history); // undefined(アクセス不可)
このパターンでは、history 変数は関数スコープの中に閉じ込められているため、外部から直接変更できません。これがスコープを活用した「情報隠蔽」です。
まとめ
- ✅ スコープ:変数が使える範囲のこと
- ✅ グローバルスコープ:どこからでも使える(関数・ブロックの外)
- ✅ ローカルスコープ:関数の中だけで使える
- ✅ ブロックスコープ:
の中だけで使える(let・const) - ✅
varはブロックスコープなし →let・constを使おう
スコープを理解すると、変数の管理がしやすくなりバグが減ります。レッスンでさらに実践的な使い方を学んでみましょう。
🚀 JavaScriptをレッスンで学ぼう!
このサイトのJavaScriptコースでは、スコープを含む実践的なプログラムをブラウザだけで学べます。無料・登録不要です。
JavaScriptコースを見る →