ローカルスコープって何者?
ローカルスコープは、
「その中だけで有効な“自分だけの部屋”みたいな領域」 です。
グローバルスコープが「家全体」だとしたら、
ローカルスコープは「自分の部屋」。
部屋の中のもの(変数)は、外からは直接触れません。
この「外から見えない」という性質が、
バグを減らしたり、コードを整理したりするうえでめちゃくちゃ重要になります。
関数が作るローカルスコープ
関数の中で宣言した変数は外から見えない
一番基本のローカルスコープは「関数スコープ」です。
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
JavaScriptlocalValue は test 関数の中で宣言されているので、
その関数の中からしか見えません。
ここが重要です。
「関数の中で宣言した変数は、その関数の“ローカルスコープ”に属する。
外からは見えないし、触れない。」
これがローカルスコープの基本です。
同じ名前でもローカルが優先される
ローカルスコープの中で、
グローバルと同じ名前の変数を宣言するとどうなるか。
let value = 1; // グローバル
function test() {
let value = 2; // ローカル(同じ名前)
console.log("関数内:", value);
}
test();
console.log("関数外:", value);
JavaScript結果はこうなります。
関数内: 2
関数外: 1
関数の中では「ローカルの value」が優先され、
外では「グローバルの value」が使われます。
ここがポイントです。
「内側のスコープに同じ名前があれば、そっちが優先される」
これを“シャドーイング(隠す)”と呼びます。
ブロックスコープ({} が作るローカルスコープ)
let / const はブロックごとにスコープを持つ
if や for の {} も、let / const にとっては「ローカルスコープ」を作ります。
if (true) {
let x = 10;
console.log("ブロック内:", x); // 10
}
console.log("ブロック外:", x); // エラー:x is not defined
JavaScriptx は if ブロックの中だけで有効です。
外からは見えません。
同じように、for でも。
for (let i = 0; i < 3; i++) {
console.log("ループ内:", i);
}
console.log("ループ外:", i); // エラー:i is not defined
JavaScriptここが重要です。let / const は「ブロック({})ごとにローカルスコープを作る」。var はそうならない(関数スコープのみ)ので、今どきは基本使わない。
ローカルスコープの“守ってくれる力”
外から勝手に書き換えられない安心感
ローカルスコープに閉じ込めた変数は、
外から直接触れません。
function createCounter() {
let count = 0; // ローカル
function increment() {
count += 1;
console.log(count);
}
return increment;
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter(); // 3
JavaScriptここで count は createCounter の中のローカル変数です。
外から count = 100; のように直接いじることはできません。
counter() を通じてしか count は変わらない。
これは「ローカルスコープが状態を守ってくれている」状態です。
ここが重要です。
ローカルスコープは「変数を外から守るカプセル」のようなもの。
“勝手に触られない”というのは、実務でかなり大きな安心材料になります。
ネストしたローカルスコープ
内側からは外側が見える、でも逆は見えない
スコープは「入れ子」になります。
function outer() {
let outerValue = "外";
function inner() {
let innerValue = "内";
console.log(outerValue); // 見える
console.log(innerValue); // 見える
}
inner();
console.log(outerValue); // 見える
console.log(innerValue); // エラー:innerValue is not defined
}
outer();
JavaScript内側の inner からは、
外側の outerValue が見えます。
でも、外側から内側の innerValue は見えません。
このルールはとても大事で、
「内側から外側は見えるけど、外側から内側は見えない」
と覚えておくとスッキリします。
実務でのローカルスコープの使いどころ
「一時的な変数」はローカルに閉じ込める
例えば、配列を処理する関数。
function sum(numbers) {
let total = 0; // ローカル
for (const n of numbers) {
total += n;
}
return total;
}
const result = sum([1, 2, 3]);
console.log(result); // 6
JavaScriptここで total は、sum の中だけで意味がある「一時的な変数」です。
これをグローバルに置く必要はまったくありません。
let total = 0; // こうすると危険
function sum(numbers) {
total = 0;
for (const n of numbers) {
total += n;
}
return total;
}
JavaScriptこう書くと、
他の場所から total を触れてしまい、
思わぬバグの原因になります。
ここが重要です。
「その処理の中だけで使う変数」は、必ずローカルスコープに閉じ込める。
スコープを狭くすることは、そのまま“安全性を高めること”につながります。
即時関数(IIFE)でローカルスコープを作る(古典的テクニック)
昔は、
グローバル汚染を避けるために「即時関数(IIFE)」で
ローカルスコープを作るテクニックがよく使われました。
(function () {
const message = "これはローカル";
console.log(message);
})();
console.log(message); // エラー:message is not defined
JavaScript今はモジュールやブロックスコープがあるので
必須ではありませんが、
「関数がスコープを作る」という感覚をつかむには良い例です。
初心者として「ローカルスコープ」で本当に押さえてほしいこと
ローカルスコープは、
「その中だけで有効な、外から見えない領域」。
関数の中で宣言した変数
ブロック({})の中で let / const で宣言した変数
は、その中からしか見えない。
内側から外側は見えるけど、
外側から内側は見えない。
この性質をうまく使うと、
一時的な変数を外に漏らさない
状態を外から勝手に書き換えられない
同じ名前の変数を別々のスコープで安心して使える
というメリットが得られます。
コードを書くとき、
「この変数はどこから見えれば十分か?」
「もっとスコープを狭くできないか?」
と一度考えてみてください。
その一歩が、
「なんとなく動くコード」から
「意図がはっきりした、壊れにくいコード」への入り口になります。
