PR

【JavaScript】スコープ(変数の有効範囲)とは?初心者向けに3分でわかりやすく解説

JavaScriptのスコープを解説する記事のアイキャッチ画像 JavaScript

JavaScriptを学び始めると、「この変数はどこから使えるのか?」で迷う場面がよくあります。結論からいうと、スコープとは、その変数をどの範囲のコードから参照できるかを表すルールです。

このルールを理解していないと、変数が思わぬ場所で書き換わったり、逆に使えると思っていた変数が使えず ReferenceError になったりします。この記事では、JavaScript初心者の方に向けて、スコープの意味、グローバルスコープ・関数スコープ・ブロックスコープの違い、varlet / const の使い分けを1からわかりやすく整理します。

まずは「スコープ = 変数が見える範囲」と押さえればOKです。

スポンサーリンク

結論:JavaScriptのスコープは主に3つある

初心者の方は、まず次の3つを区別できれば十分です。

種類 意味 代表例
グローバルスコープ プログラム全体から参照できる範囲 ファイルの一番外側で宣言した変数
関数スコープ その関数の中だけで使える範囲 var や引数で宣言した変数
ブロックスコープ { } の中だけで使える範囲 letconst で宣言した変数

ポイント JavaScriptのスコープでいちばん大事なのは、var は関数スコープ、letconst はブロックスコープだという違いです

そもそもスコープ(変数の有効範囲)とは?

スコープとは、変数や定数が「どこで使えるか」を決める仕組みです。

たとえば、ある if 文の中でだけ必要な変数があるとします。その変数をプログラム全体から触れる状態にしてしまうと、関係のない場所から誤って使われたり、値を上書きされたりする可能性があります。

逆に、必要な場所だけで使えるようにしておけば、コードの見通しが良くなり、バグも起きにくくなります。つまりスコープは、「変数を安全に使うための境界線」のようなものです。

1. グローバルスコープ

グローバルスコープは、プログラムの広い範囲から参照できるスコープです。ブラウザで通常の script タグを使う場面などでは、ファイルの一番外側で宣言した変数は広い範囲から参照できます。

const siteName = "Biz Online";

function showSiteName() {
  console.log(siteName);
}

showSiteName(); // Biz Online

この例では、siteName は関数の外で宣言されているため、showSiteName() の中からでも参照できます。

ただし、グローバル変数を増やしすぎると、どこからでも触れるぶん管理が難しくなります。初心者のうちは、本当に広い範囲で必要なものだけをグローバルに置くと覚えておくと安心です。

2. 関数スコープ

関数スコープとは、その関数の中だけで有効な範囲です。関数の引数や、関数内で var で宣言した変数は、その関数の外からは使えません。

function greet(name) {
  var message = "こんにちは、" + name + "さん";
  console.log(message);
}

greet("田中");
// console.log(message); // ReferenceError

この例の message は、greet() の中でだけ使える変数です。関数の外に出ると参照できません。

JavaScriptの関数の基本を学ぶときも、この「関数の中で作った変数は外では使えない」という感覚を持っておくと理解しやすくなります。

3. ブロックスコープ

ブロックスコープとは、if 文や for 文、あるいは単なる { } の中だけで有効な範囲です。letconst はこのブロックスコープに従います。

if (true) {
  let count = 10;
  const message = "ブロックの中だけで使える";

  console.log(count);   // 10
  console.log(message); // ブロックの中だけで使える
}

// console.log(count);   // ReferenceError
// console.log(message); // ReferenceError

このように、letconst で宣言した変数は、ブロックの外では使えません。これが、現代のJavaScriptで var より let / const がよく使われる大きな理由です。

var と let / const では何が違うのか

スコープの話で初心者がつまずきやすいのは、var だけ挙動が違うことです。

if (true) {
  var oldValue = "varで宣言";
  let newValue = "letで宣言";
}

console.log(oldValue); // varで宣言
// console.log(newValue); // ReferenceError

上のコードでは、oldValueif ブロックの外からも参照できます。これは var がブロックスコープを持たず、関数スコープで動くためです。

一方、newValuelet で宣言されているため、if ブロックの外では使えません。

そのため、いまからJavaScriptを書くなら、基本的には次の考え方で大丈夫です。

  • 再代入する変数は let
  • 再代入しない値は const
  • var は古いコードを読むときに出てくるもの、と考える

JavaScriptの変数宣言(let / const / var)の記事も合わせて読むと、スコープの違いがさらに整理しやすくなります。

外側の変数は内側から見える

JavaScriptでは、内側の関数から外側の変数を参照できます。

const outerMessage = "外側の変数";

function outer() {
  const innerValue = 100;

  function inner() {
    console.log(outerMessage);
    console.log(innerValue);
  }

  inner();
}

outer();

この例では、inner() の中から外側にある outerMessageinnerValue を参照できます。逆に、外側から内側のローカル変数を勝手に見ることはできません。JavaScriptでは、このように「関数が定義された位置関係」によって参照できる範囲が決まります。

この考え方は、関数式アロー関数を学ぶときにも土台になります。

覚え方 JavaScriptのスコープは「内側は外側を見られるが、外側は内側を見られない」と考えると整理しやすいです

よくあるつまずき

1. if の中で作った変数が外で使えない

letconst はブロックスコープなので、if 文や for 文の外では使えません。これは不具合ではなく、意図どおりの動作です。

2. var を使ったら外でも見えてしまう

var はブロックスコープを持たないため、初心者が「なぜ使えてしまうのか」で混乱しやすいです。新しく書くコードでは、なるべく let / const を使うほうが安全です。

3. 同じ名前の変数を内側で再宣言してしまう

const message = "外側";

function sample() {
  const message = "内側";
  console.log(message); // 内側
}

sample();
console.log(message);   // 外側

このように同じ名前でも、スコープが違えば別の変数として扱われます。便利なこともありますが、初心者のうちは混乱しやすいので、なるべく分かりやすい名前を付けるのがおすすめです。

補足:スコープを図で見ると、変数の置き場所が分かりやすい

スコープは文章だけで理解しようとすると、少し抽象的に感じやすいです。そこで、変数が見える範囲を「外側から内側へ入っていく箱」として見ると整理しやすくなります。

JavaScriptのグローバルスコープ関数スコープブロックスコープを示した図
グローバル、関数、ブロックの順に、変数が見える範囲が変わります。

この図で見てほしいのは、外側に置いた変数ほど見える範囲が広く、内側に置いた変数ほど見える範囲が狭くなることです。グローバルスコープに置いた変数は便利ですが、いろいろな場所から触れてしまうため、意図しない変更が起きやすくなります。

一方で、関数の中だけ、ブロックの中だけに変数を置けば、その変数を使える場所が限定されます。これは不便に見えるかもしれませんが、実務ではむしろ安全です。フォーム入力の一時的な値、ループ内でだけ使うカウンタ、ボタン処理の中だけで使うメッセージなどは、必要な範囲に閉じ込めたほうが読みやすくなります。

次に、varlet の違いをコードと結果で見てみます。スコープの記事で特に大切なのは、同じ { } の中で宣言しても、宣言方法によって外側から見えるかどうかが変わる点です。

JavaScriptのvarとletのスコープの違いをコードと結果で示した図
varはifブロックの外でも見えますが、letはifブロックの外では見えません。

この画像では、avar で宣言しているため、if ブロックの外からも参照できています。一方で、blet で宣言しているため、ブロックの外から参照するとエラーになります。

初心者の方は、まず「letconst{ } の中に閉じる」と覚えると実用的です。もちろん細かい例外や発展的な話はありますが、最初の理解としてはこの整理で十分です。

for (let i = 0; i < 3; i++) {
  console.log(i);
}

// console.log(i); // ここでは使えない

このように、ループの中でだけ使う変数は let で宣言すると、外側へ余計に漏れません。あとから読む人も「この変数はループ専用だ」と分かるため、コードの見通しが良くなります。

スコープの理解は、let・const・var の違いfunction(関数) の理解にもつながります。変数の置き場所を意識できるようになると、エラーの原因を探す力もかなり上がります。

実務でスコープを意識する場面

スコープを意識する場面は、思っているより多いです。たとえば、フォームの入力値をチェックする処理では、入力欄ごとに一時的な変数を使うことがあります。その変数が画面全体から見えてしまうと、別の入力欄の処理と名前がぶつかったり、意図しない値で上書きされたりします。

また、ループの中で使うカウンタや一時的な判定結果も、必要な範囲だけに閉じ込めると安全です。処理が長くなったときほど、「この変数はどこから見えるのか」を意識しておくと、デバッグが楽になります。

エラーが出たときの見直しポイント

  • ReferenceError が出たら、その変数が今の場所から見えるか確認する
  • 値が思ったものと違う場合、外側の同名変数を使っていないか確認する
  • var が古いコードに残っている場合、ブロックの外へ漏れていないか確認する
  • 一時的な変数は、できるだけ使う場所の近くで宣言する

もうひとつの確認ポイントは、同じ名前の変数を内側で作っていないかどうかです。外側にも message があり、内側にも message があると、今どちらを見ているのか分かりにくくなります。慣れないうちは、役割が違う変数には少し具体的な名前を付けると安全です。

たとえば、画面全体で使うメッセージなら pageMessage、フォームの中だけで使うなら formMessage のように名前を分けます。スコープと変数名をセットで考えると、コードの意図がかなり伝わりやすくなります。

スコープは、最初は見えないルールのように感じます。しかし、変数の置き場所を整理するための仕組みだと考えると、コード全体の読みやすさを守るための大事な道具になります。

注意点として、グローバルスコープに変数を置きすぎると、別のファイルや別の処理から同じ名前を使ったときに衝突しやすくなります。小さな練習コードでは問題が見えにくいですが、画面や機能が増えるほど影響が大きくなります。

よくあるミスは、「どこでも使えるほうが便利」と考えて、必要以上に外側へ変数を置いてしまうことです。便利に見える反面、どの処理が値を変えたのか分からなくなり、原因調査に時間がかかります。

変数は、使う場所にできるだけ近いところで宣言すると読みやすくなります。ボタン処理だけで使う値ならボタン処理の中、ループだけで使う値ならループの中、関数全体で必要な値なら関数の先頭付近、というように置き場所を考えます。

この考え方を身につけると、ReferenceError が出たときも落ち着いて確認できます。エラー文の変数名を見て、その変数が今いる場所から見える範囲に宣言されているかを順番に見直せば、原因にたどり着きやすくなります。

また、スコープを意識すると、関数をどこで分けるべきかも判断しやすくなります。必要な値を外側から無理に共有するより、関数の引数として渡したほうが、処理の関係が明確になることがあります。

JavaScriptを体系的に学びたい方は

スコープの理解を深めたい方は、次の記事もあわせて読むと流れがつかみやすいです。

まとめ

まとめ JavaScriptのスコープで押さえたいこと

  • スコープとは、変数が使える範囲のこと
  • 主にグローバルスコープ、関数スコープ、ブロックスコープがある
  • var は関数スコープ、letconst はブロックスコープ
  • 内側の関数からは外側の変数を参照できる
  • 初心者のうちは letconst を中心に使うと整理しやすい

JavaScriptのスコープは、一見すると地味なルールですが、変数の扱い方やバグの防止に直結する大事な基本です。まずは「どこで宣言した変数が、どこから見えるのか」を意識しながらコードを書くようにすると、理解がかなり進みます。

タイトルとURLをコピーしました