JavaScript | 基礎構文:スコープ・実行コンテキスト - 関数スコープ

JavaScript JavaScript
スポンサーリンク

関数スコープって何者?

関数スコープは、
「その関数の中だけで有効な“専用の部屋”」 のことです。

関数の中で宣言した変数や関数は、
基本的にその関数の外からは見えません。

「関数ごとに、自分だけの小さな世界を持っている」
それが関数スコープです。


一番シンプルな関数スコープの例

関数の中の変数は外から見えない

function test() {
  let x = 10; // test 関数のローカル変数(関数スコープ)
  console.log("関数内:", x);
}

test();

console.log("関数外:", x); // エラー: x is not defined
JavaScript

xtest 関数の中で宣言されています。
このとき x は「test 関数のスコープ」に属します。

関数の中では x を自由に使えますが、
関数の外からは x は存在しないことになっています。

ここが重要です。
「関数の中で宣言した変数は、その関数の中だけで有効」
これが関数スコープの基本ルールです。


グローバルスコープとの対比で理解する

外側(グローバル)と内側(関数)の関係

let globalValue = 1; // グローバルスコープ

function showValues() {
  let localValue = 2; // 関数スコープ
  console.log("関数内 globalValue:", globalValue); // 1
  console.log("関数内 localValue:", localValue);   // 2
}

showValues();

console.log("関数外 globalValue:", globalValue); // 1
console.log("関数外 localValue:", localValue);   // エラー
JavaScript

関数の中からは、
外側(グローバル)の globalValue も見えます。

でも、外側から内側の localValue は見えません。

この関係はとても大事で、

内側から外側は見える
外側から内側は見えない

というルールになっています。

ここが重要です。
スコープは「内側ほど限定的」で、「外側ほど広い」。
内側は外側を“見上げられる”けど、外側は内側を“覗けない”。


var と関数スコープ(歴史的に重要なポイント)

var は「関数スコープ」しか持たない

let / const は「ブロックスコープ」ですが、
var は「関数スコープ」しか持ちません。

if (true) {
  var x = 10;
}
console.log(x); // 10(見えてしまう)
JavaScript

var{} をスコープとして扱わないので、
if の外からも x が見えてしまいます。

しかし、関数の中で宣言した var は、
その関数の外からは見えません。

function test() {
  var y = 20;
  console.log("関数内:", y); // 20
}

test();
console.log("関数外:", y); // エラー: y is not defined
JavaScript

このように、
var にとって「スコープを作るのは関数だけ」 です。

今どきは var をあまり使いませんが、
「関数スコープ」という言葉がよく出てくるのは、
この var の性質とセットで語られることが多いからです。


関数スコープが“守ってくれる”もの

一時的な変数を外に漏らさない

関数スコープのおかげで、
「その関数の中だけで使う変数」を外に漏らさずに済みます。

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

// console.log(total); // エラー: total is not defined
JavaScript

totalsum の中だけで意味がある変数です。
関数スコープに閉じ込めることで、

他の関数からうっかり触られる
別の場所で同じ名前を使って壊される

といったリスクを減らせます。

ここが重要です。
「その関数の中だけで使うものは、その関数のスコープに閉じ込める」
これは安全で読みやすいコードを書くうえで、かなり大事な感覚です。


関数の中に関数を定義するとどうなるか

ネストした関数とスコープの入れ子

function outer() {
  let outerValue = "外";

  function inner() {
    let innerValue = "内";
    console.log(outerValue); // 見える
    console.log(innerValue); // 見える
  }

  inner();

  console.log(outerValue); // 見える
  // console.log(innerValue); // エラー
}

outer();
JavaScript

ここでのスコープの関係は、

outer のスコープ:outerValue
inner のスコープ:outerValue, innerValue

という入れ子になっています。

innerouter の中で定義されているので、
outer のスコープを“外側”として持っています。

外側から内側の innerValue は見えませんが、
内側から外側の outerValue は見えます。

この「関数の中に関数を定義する」構造が、
クロージャやレキシカルスコープの話につながっていきます。


即時関数(IIFE)と関数スコープ(古典的テクニック)

「グローバルを汚さないための関数スコープ」

昔の JavaScript では、
モジュールがなかったので、
「グローバル変数だらけ」になりがちでした。

それを避けるために、
「即時関数(IIFE)」で関数スコープを作るテクニックがよく使われました。

(function () {
  const message = "これはローカル";
  console.log(message); // OK
})();

console.log(message); // エラー: message is not defined
JavaScript

(function () { ... })() の中は、
その関数専用のスコープです。

中で宣言した変数は外から見えないので、
グローバルを汚さずにコードを書けます。

今は ES Modules があるので必須ではありませんが、
「関数がスコープを作る」という感覚をつかむには、
このパターンはとても分かりやすい例です。


実務で「関数スコープ」をどう意識するか

「この変数はどこまで見えれば十分か?」と考える

関数スコープを意識するというのは、
言い換えると、

「この変数は、どの範囲から見えれば十分か?」

を考えることです。

その関数の中だけで使うなら、
関数の中で宣言する(ローカルにする)。

複数の関数から共有したいなら、
一つ外側のスコープに置く。

それでも足りなければ、
モジュールやクラスなど、別の単位でまとめる。

こうやって「スコープの広さ」を意識して決めていくと、
コードの見通しが一気によくなります。

ここが重要です。
スコープは「とりあえず広くしておくもの」ではなく、
“必要最小限に狭くするもの”。
関数スコープは、そのための基本単位です。


初心者として「関数スコープ」で本当に押さえてほしいこと

関数スコープは、

「関数の中で宣言したものは、その関数の中だけで有効」

というルールです。

内側の関数からは外側の変数が見えるけれど、
外側から内側の変数は見えない。

この性質のおかげで、

一時的な変数を外に漏らさずに済む
関数ごとに“自分だけの世界”を持てる
グローバル変数だらけにならずに済む

というメリットがあります。

コードを書くとき、
「この変数、本当はこの関数の中だけでよくない?」
と一度問いかけてみてください。

その問いかけを繰り返すうちに、
あなたは「なんとなく変数を置く人」から、
「スコープを設計できるプログラマー」 に変わっていきます。

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