JavaScript | 基礎構文:変数・定数 – グローバル変数の扱い

JavaScript
スポンサーリンク

まず「グローバル変数」とは何か

グローバル変数は、
「プログラムの“どこからでも”読めて・書けてしまう変数」 のことです。

もう少し具体的に言うと、

どの関数の中にも入っていない場所
(ファイルの一番上とか)

で宣言された変数は、多くの場合「グローバル変数」になります。

let count = 0; // グローバル変数(どこからでも見える)

function increment() {
  count = count + 1; // ここからも触れる
}

increment();
console.log(count); // 1
JavaScript

increment 関数の中でも、外でも、
count に自由にアクセスできています。

ここが重要です。
「どこからでも見える」=「どこからでも壊せる」
ということでもあるので、グローバル変数は強力で便利な反面、扱いを間違えるとすぐにカオスになります。


なぜグローバル変数が「危ない」と言われるのか

どこで書き換えられたか分かりにくくなる

例えば、こんなコードを考えます。

let status = "INIT";  // グローバル変数

function start() {
  status = "RUNNING";
}

function stop() {
  status = "STOPPED";
}

function debug() {
  console.log("現在の状態:", status);
}
JavaScript

小さな例ならまだしも、
実際のアプリではファイルが何十・何百と増えたりします。

その中のあちこちで status = ... と書かれていると、

「今の status は、どのタイミングで、どの関数によって変わったのか?」

を追いかけるのがだんだん難しくなっていきます。

デバッグ中にこんなことが起こります。

「さっきまで status が RUNNING だったのに、いつの間にか STOPPED になってる…」
「どこで変わったのかログを入れて調べまくる」

つまり、
グローバル変数は「触る人」が多すぎて、変更元の特定が難しくなりがち です。

名前の衝突(上書き事故)が起きやすい

グローバル変数は「みんなの共有スペース」に置いた変数です。

自分のファイルで let data = ... と書いていて、
どこか別のファイルでも let data = ... をグローバルに書いていると、
意図せず上書きし合う ことがあります。

小規模なコードならまだしも、
ライブラリや他人のコードも混ざってくると、

「あっちの data と、こっちの data が同じ名前だったせいでバグった」

みたいなことが本当に起きます。

テストや再利用が難しくなる

ある関数が「グローバル変数に依存している」と、
その関数単体をテスト・再利用しづらくなります。

let taxRate = 0.1;

function calcTotal(price) {
  return price + price * taxRate;
}
JavaScript

一見シンプルですが、この関数は taxRate というグローバル変数に依存しています。

他のプロジェクトで calcTotal だけ持っていこうとしても、
taxRate もセットで持っていかなければ動きません。

ここが重要です。
グローバル変数に依存する関数は、「その関数だけを持ち出す」「設定を変える」といった再利用性・テスト性を犠牲にしがち。


とはいえ「グローバルに置きたいもの」もある

完全に悪ではない:全体設定・定数など

実務では、「アプリ全体で共有したい情報」も存在します。

例えば:

アプリ名
バージョン
API のベース URL
環境情報(開発・本番など)

こういったものは、
全体から参照できたほうが素直 なケースもあります。

const APP_NAME = "MyApp";
const API_BASE_URL = "https://api.example.com";

function showTitle() {
  console.log(APP_NAME);
}

function fetchUser() {
  return fetch(`${API_BASE_URL}/user`);
}
JavaScript

このような 「変わらない定数」 については、
「グローバルに近い場所にまとめて定義する」のはむしろ自然な設計です。

「何でもかんでもグローバル」はダメ、「必要最小限だけグローバル」はアリ

重要なのは、

何でもかんでもグローバルに置くのではなく、
「アプリ全体の前提になる値」だけを厳選してグローバルにする
というバランス感覚です。

「1つの画面だけでしか使わない一時変数」までグローバルにする必要はありません。
そういうものは、できるだけ関数やブロックの中に閉じ込めるべきです。

ここが重要です。
**グローバル変数を「完全禁止」にするのではなく、

  • 原則:使わない
  • 例外:アプリ全体の設定/定数だけ、厳選して使う
    という考え方が現実的な落としどころです。**

JavaScript における「グローバル」の具体的なイメージ

ブラウザなら window(グローバルオブジェクト)

ブラウザ環境では、
グローバル変数は裏側で window オブジェクトのプロパティになります。

var foo = 123;
console.log(window.foo); // 123
JavaScript

var でグローバル宣言すると、
window.foo としても見えてしまいます。

一方で、let / const でグローバルに書いた変数は、
window のプロパティにはなりません(仕様の違い)。

let bar = 456;
console.log(window.bar); // undefined
console.log(bar);        // 456
JavaScript

とはいえ、ブラウザでは
「どの関数にも入っていない let / const」も、
「そのファイル内の“トップレベルでどこからでも使える変数”」

という意味では、「グローバルに近い存在」です。

Node.js では少し事情が違う(が、初心者は「ファイルごとに閉じる」と覚えればOK)

Node.js では、各ファイルがモジュールとして扱われるため、
ファイルのトップレベルで宣言した let / const は、
そのファイル内でのみ有効 です。

これを「モジュールスコープ」と呼びます。

Node の世界では、「本当の意味でのグローバル」をむやみに使うことは推奨されません。
初心者のうちは、

「Node では、let / const はそのファイル専用の変数」
「他のファイルから使いたいものは、export / import を使う」

くらいの認識で十分です。


グローバル変数をどう「減らす」か:実践的な考え方

1: 本当に必要か、自分に問いかける

何か変数をトップレベルに置こうとしたとき、
一度こう自問してみてください。

「この値、どの関数からでもアクセスできる必要が本当にある?」
「特定の処理の中だけで完結しない?」

たとえば:

ユーザーの一時選択状態
一回の処理の途中でしか使わない計算結果

などは、その処理の中のローカル変数で十分です。

function process() {
  let temp = calculate();
  console.log(temp);
  // temp はこの関数の中だけで十分
}
JavaScript

2: 必要な値は「引数」と「戻り値」で渡せないか考える

グローバル変数に頼るのではなく、
「必要な値は引数で渡す」
という発想を徹底すると、
グローバル依存をかなり減らせます。

悪い例:

let taxRate = 0.1;

function calcTotal(price) {
  return price + price * taxRate;
}
JavaScript

良い例:

function calcTotal(price, taxRate) {
  return price + price * taxRate;
}

const TAX_RATE = 0.1;
const total = calcTotal(1000, TAX_RATE);
JavaScript

calcTotal は、
グローバル変数に依存せず、「もらった値だけ」で仕事をする関数 になりました。
そのぶん、テストしやすく、再利用もしやすくなります。

3: どうしても共有したい状態は「オブジェクトにまとめる」

アプリ全体でちょっとした状態を共有したいとき、
バラバラのグローバル変数を増やす代わりに、
一つのオブジェクトにまとめる のも良い方法です。

const appState = {
  user: null,
  isLoggedIn: false,
};

function login(user) {
  appState.user = user;
  appState.isLoggedIn = true;
}

function logout() {
  appState.user = null;
  appState.isLoggedIn = false;
}
JavaScript

appState 自体はグローバルな存在ですが、
「アプリの状態は基本ここに集約される」というルールにしておくと、
「どこで何が変わるのか」を追いやすくなります。

ここが重要です。
グローバル変数をゼロにするのが目的ではない。
「むやみにバラけさせない」「必要なものだけに限定する」「扱いを分かりやすくする」ことが大事。


初心者向けの「グローバル変数の扱い」まとめ

最後に、シンプルに整理します。

グローバル変数とは、「プログラムのどこからでも見える・書ける変数」のこと。

便利だが、

  • どこで書き換えられたか分かりにくい
  • 名前の衝突・上書き事故が起きやすい
  • テストや再利用が難しくなる
    といった問題を抱えやすい。

完全な悪者ではなく、
アプリ名・API のベース URL・定数など、「アプリ全体の前提となる情報」を置く場所としては有効。

ただし原則としては、

  • まずローカル変数(関数の中・ブロックの中)で済ませられないか考える
  • 値はできるだけ引数と戻り値で受け渡しする
  • どうしても共有したい状態は、オブジェクトなどにまとめて「ここだけで管理する」と決める

ここが重要です。
「とりあえずグローバルに置く」ではなく、「本当にここに置くべきか?」と一度立ち止まる習慣を持つこと。
それだけで、将来の自分がデバッグで泣く回数が確実に減ります。

もしよければ、

グローバル変数を 1 つだけ使っている小さなサンプル(例えば let count = 0;)を書き、
それを「関数の引数+戻り値」で書き換える練習をしてみてください。

「この値、本当にグローバルじゃないとダメだった?」
と自分に問いかけて変形させてみることが、
グローバル変数との上手な距離感をつかむ近道になります。

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