JavaScript | 基礎構文:スコープ・実行コンテキスト - ローカルスコープ

JavaScript JavaScript
スポンサーリンク

ローカルスコープって何者?

ローカルスコープは、
「その中だけで有効な“自分だけの部屋”みたいな領域」 です。

グローバルスコープが「家全体」だとしたら、
ローカルスコープは「自分の部屋」。
部屋の中のもの(変数)は、外からは直接触れません。

この「外から見えない」という性質が、
バグを減らしたり、コードを整理したりするうえでめちゃくちゃ重要になります。


関数が作るローカルスコープ

関数の中で宣言した変数は外から見えない

一番基本のローカルスコープは「関数スコープ」です。

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

localValuetest 関数の中で宣言されているので、
その関数の中からしか見えません。

ここが重要です。
「関数の中で宣言した変数は、その関数の“ローカルスコープ”に属する。
外からは見えないし、触れない。」

これがローカルスコープの基本です。

同じ名前でもローカルが優先される

ローカルスコープの中で、
グローバルと同じ名前の変数を宣言するとどうなるか。

let value = 1; // グローバル

function test() {
  let value = 2; // ローカル(同じ名前)
  console.log("関数内:", value);
}

test();
console.log("関数外:", value);
JavaScript

結果はこうなります。

関数内: 2
関数外: 1

関数の中では「ローカルの value」が優先され、
外では「グローバルの value」が使われます。

ここがポイントです。
「内側のスコープに同じ名前があれば、そっちが優先される」
これを“シャドーイング(隠す)”と呼びます。


ブロックスコープ({} が作るローカルスコープ)

let / const はブロックごとにスコープを持つ

iffor{} も、
let / const にとっては「ローカルスコープ」を作ります。

if (true) {
  let x = 10;
  console.log("ブロック内:", x); // 10
}

console.log("ブロック外:", x); // エラー:x is not defined
JavaScript

xif ブロックの中だけで有効です。
外からは見えません。

同じように、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

ここで countcreateCounter の中のローカル変数です。
外から 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 で宣言した変数

は、その中からしか見えない。

内側から外側は見えるけど、
外側から内側は見えない。

この性質をうまく使うと、

一時的な変数を外に漏らさない
状態を外から勝手に書き換えられない
同じ名前の変数を別々のスコープで安心して使える

というメリットが得られます。

コードを書くとき、
「この変数はどこから見えれば十分か?」
「もっとスコープを狭くできないか?」

と一度考えてみてください。

その一歩が、
「なんとなく動くコード」から
「意図がはっきりした、壊れにくいコード」への入り口になります。

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