スコープってそもそも何?その中の「グローバルスコープ」とは
まず前提として、スコープとは
「変数や関数が“どこから見えるか(使えるか)”の範囲 のことです。
その中で「グローバルスコープ」は、
「プログラム全体から見える、一番外側のスコープ」 です。
ざっくり言うと、
「どこからでもアクセスできる場所に置かれた変数・関数」が
グローバルスコープに属している、というイメージです。
グローバルスコープの基本イメージ
一番外側に書いた変数は全部グローバル
まずはシンプルな例から見てみましょう。
let count = 0; // グローバルスコープ
function increment() {
count += 1; // ここからも見える
}
increment();
console.log(count); // 1
JavaScriptlet count = 0; は、
関数の中でもブロックの中でもなく、
「ファイルの一番外側」に書かれています。
このような変数は、
そのファイル内のどこからでもアクセスできます。
これがグローバルスコープの変数です。
ここが重要です。
「一番外側に書いたものは、そのファイル全体から見える」
これがグローバルスコープの基本イメージです。
ブラウザ環境でのグローバルスコープ
window オブジェクトとグローバル変数
ブラウザでは、
グローバルスコープの“持ち主”は window オブジェクトです。
var x = 10;
console.log(window.x); // 10
JavaScriptvar で宣言したグローバル変数は、window のプロパティとしてもアクセスできます。
一方、let や const は
グローバルでも window のプロパティにはなりません。
let y = 20;
console.log(window.y); // undefined
console.log(y); // 20
JavaScriptここが少しややこしいのですが、
「グローバルスコープにある」ことと
「window のプロパティである」ことは、今どきは必ずしもイコールではない
と覚えておくとよいです。
ただし、どちらも
「どこからでも参照できる」という意味では同じです。
Node.js やモジュール環境でのグローバルスコープ
ファイルごとに“外側”が変わる世界
Node.js や ES Modules では、
ブラウザのように「全部が1つのグローバル」ではなく、
ファイルごとにスコープが分かれます。
// a.js
let value = 1;
// b.js
console.log(value); // エラー:ここからは見えない
JavaScriptモジュールとして読み込む世界では、
「ファイルの外側に書いた変数」は
そのファイルの中だけで有効な“モジュールスコープ”になります。
この場合、
本当の意味での「アプリ全体のグローバル」はglobalThis などを使ってアクセスします。
globalThis.shared = 123;
JavaScriptただ、初心者のうちは
「ブラウザの <script> 直書きなら、外側に書いたものは全部グローバル」
「モジュールでは、ファイルの外側はそのファイル専用のスコープ」
くらいの理解で十分です。
グローバルスコープの“便利さ”と“危険さ”
便利なところ:どこからでも使える
グローバル変数は、
どこからでもアクセスできるので、
最初はとても便利に感じます。
let userName = "太郎";
function greet() {
console.log("こんにちは、" + userName + "さん");
}
greet(); // こんにちは、太郎さん
JavaScriptどの関数からでも userName を参照できるので、
「共通の設定」「アプリ全体で共有したい状態」などを
グローバルに置きたくなる気持ちはよく分かります。
危険なところ:どこからでも“壊せてしまう”
しかし、
どこからでも見えるということは、
どこからでも書き換えられる、ということでもあります。
let userName = "太郎";
function changeName() {
userName = "花子"; // どこかで勝手に変えられる
}
changeName();
console.log(userName); // 花子
JavaScriptコードが大きくなると、
「どこで値が変わったのか分からない」
「別のファイルで同じ名前の変数を使って上書きしてしまった」
といった問題が起きやすくなります。
ここが重要です。
グローバルスコープは「どこからでも見える」代わりに
「どこからでも壊せてしまう」ので、乱用するとバグの温床になる。
意図せずグローバル変数を作ってしまう罠
宣言を忘れると自動的にグローバル(古い書き方)
厳密モード("use strict")でない古い書き方では、
変数宣言を忘れると勝手にグローバル変数が作られてしまいます。
function foo() {
x = 10; // var / let / const をつけていない
}
foo();
console.log(x); // 10(グローバル変数として作られてしまう)
JavaScriptこれは非常に危険な挙動なので、
今どきは必ず use strict やモジュールを使い、let / const を必ず書くのが前提です。
"use strict";
function foo() {
x = 10; // ReferenceError: x is not defined
}
JavaScriptここが重要です。
「宣言を忘れるとグローバルになる」は“昔の罠”として覚えておき、
必ず let / const をつける癖をつけること。
グローバルスコープとローカルスコープの違いを体感する
関数の中で宣言した変数は外から見えない
グローバルと対になるのが「ローカルスコープ」です。
関数の中で宣言した変数は、その関数の中からしか見えません。
let globalValue = 1; // グローバル
function test() {
let localValue = 2; // ローカル(関数スコープ)
console.log(globalValue); // 1(見える)
console.log(localValue); // 2(見える)
}
test();
console.log(globalValue); // 1
console.log(localValue); // エラー:localValue is not defined
JavaScriptここでのポイントは、
グローバルは「どこからでも見える」
ローカルは「そのスコープの中からだけ見える」
という対比です。
この違いを意識すると、
「これはグローバルに置くべきか?ローカルに閉じ込めるべきか?」
という設計の感覚が育っていきます。
実務的な「グローバルスコープ」との付き合い方
原則:グローバルは“最小限”にする
実務では、
「グローバルはできるだけ減らす」
というのが基本方針です。
理由はシンプルで、
グローバルが多いほど「どこからでも壊せる状態」が増えるからです。
代わりに、
関数の引数として値を渡す
モジュールとして分割し、必要なものだけ export/import する
クラスやオブジェクトに閉じ込める
といった形で、
「スコープを小さく保つ」設計をします。
それでもグローバルに置くもの
とはいえ、
「アプリ全体で共有する設定」
「ライブラリそのもの」
など、グローバルに置く意味があるものもあります。
その場合は、
名前空間用のオブジェクトを1つだけグローバルに置き、
その中にまとめる、というパターンがよく使われます。
const App = {
config: {
apiBaseUrl: "https://example.com/api",
},
state: {
user: null,
},
};
App.state.user = { name: "太郎" };
console.log(App.state.user.name); // 太郎
JavaScriptこうすると、
「バラバラのグローバル変数」ではなく
「App という1つのグローバルオブジェクト」に集約できるので、
衝突や混乱が減ります。
初心者として「グローバルスコープ」で本当に押さえてほしいこと
グローバルスコープは、
「一番外側にある“どこからでも見える領域”」 です。
一番外側に書いた変数・関数は、
そのファイル全体からアクセスできる。
それは便利だけど、
どこからでも書き換えられる=バグの原因にもなりやすい。
だからこそ、
「これは本当にグローバルにする必要があるか?」
「この値は関数の引数で渡せないか?」
「この状態はオブジェクトやモジュールに閉じ込められないか?」
と一度立ち止まって考えるクセが大事です。
最初のうちは、
グローバル変数を使っても構いません。
ただ、「なんとなく」ではなく、
「ここはあえてグローバルにしている」と自覚して使う こと。
その意識があるだけで、
あなたのコードは一気に“雑なスクリプト”から
“設計されたプログラム”に近づいていきます。
