JavaScriptのスコープとは?初心者向けにわかりやすく解説

JavaScriptスコープを初心者向けに解説。グローバル・ローカル・ブロックスコープの違いとlet・const・varの挙動の違いをコード例で紹介。中高生向け。無料。

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); // エラー!関数の外からは使えない

ブロックスコープ:{}の中だけで使える

letconstブロックスコープ を持ちます。 の中で宣言した変数は、その の中だけで使えます。

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 はブロックスコープを持たないため、 の外からでも使えてしまいます。これがバグの原因になりやすいため、現在は letconst を使うことが推奨されています。

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

countcreateCounter の中で定義されていますが、返された関数からアクセスし続けられます。これがクロージャです。

よくある間違い

  • 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 はブロックスコープなし → letconst を使おう

スコープを理解すると、変数の管理がしやすくなりバグが減ります。レッスンでさらに実践的な使い方を学んでみましょう。

🚀 JavaScriptをレッスンで学ぼう!

このサイトのJavaScriptコースでは、スコープを含む実践的なプログラムをブラウザだけで学べます。無料・登録不要です。

JavaScriptコースを見る →
目次

コースで実際に手を動かして学ぼう

レッスンではコードを書きながら基礎が身につきます

HTMLコースを始める →

この記事に出てくる用語

📣 この記事が役に立ったら

Xでシェア

💬 引用する場合はこちらをご利用ください:

JavaScriptスコープを初心者向けに解説。グローバル・ローカル・ブロックスコープの違いとlet・const・varの挙動の違いをコード例で紹介。中高生向け。無料。

出典: https://start-web-programming.com/blog/javascript-scope/