JavaScript’s local scope refers to the range of variables that is only valid within a specific function or block, preventing external access and thereby serving as an important mechanism to avoid variable conflicts and enhance security.
ローカルスコープ(局所スコープ)とは、ある範囲(関数やブロック)内でのみ有効となる変数や定数の有効範囲のことを指します。スコープ(Scope)は「変数が参照可能な範囲」を意味し、JavaScriptでは主に以下のように分類されます。
{}
)の内部でのみアクセス可能なスコープローカルスコープを理解することで、変数の管理やコードの保守性を高めることができます。
ローカルスコープの導入目的は、変数名の衝突や意図しない値の上書きを防ぎ、コードの可読性や安全性を高めることにあります。大規模なプロジェクトでは大量の変数が出現するため、グローバルスコープだけで変数を管理するとバグの原因になりやすいです。
以下に、ローカルスコープのメリットをシンプルにまとめます。
グローバルスコープとは、JavaScript全体(ブラウザ環境ではwindow
オブジェクト、Node.js環境ではglobal
オブジェクトなど)で参照可能なスコープです。グローバル変数はどこからでもアクセスできるため便利に思えますが、スコープ外から値を変更されやすいというリスクがあります。
古くからのJavaScriptでは、関数単位でスコープが作られるのが基本でした。つまり、function
で囲んだブロック内で宣言された変数(var
)は、その関数内でのみ有効となります。関数の外からは一切アクセスできません。
JavaScript
function myFunction() {
var x = 10;
console.log(x); // 10
}
console.log(x); // ReferenceError: x is not defined
上記の例では、x
はmyFunction
関数内で宣言されているため、関数の外ではアクセスできません。
ES6(ECMAScript 2015)から導入されたlet
やconst
は、ブロック単位({ }
で囲まれた範囲)でスコープが作られます。
例えば、if
文やfor
ループなどのブロック内で宣言した変数は、そのブロックの外からは参照できません。
JavaScript
{
let y = 20;
const z = 30;
console.log(y); // 20
console.log(z); // 30
}
console.log(y); // ReferenceError: y is not defined
console.log(z); // ReferenceError: z is not defined
ブロックスコープを活用することで、より細かい単位で変数の有効範囲を管理できるようになり、意図しない変数の衝突を防ぐことができます。
var
で宣言した変数は、関数の中であればどこでもアクセス可能。var
で再宣言してもエラーにならない(ただし意図しない上書きの原因になる)。{}
で囲んだ範囲内でのみ有効。const
は再代入不可**ホイスティング(変数の巻き上げ)とは、JavaScriptのエンジンがコードを解釈する際に、変数宣言をスコープの先頭に移動させる仕組みのことです。var
の場合は宣言が完全に持ち上げられ、宣言前でも参照できてしまいます(ただし値はundefined
)。一方、let
とconst
の場合はTDZ(Temporal Dead Zone)**という概念が導入されているため、宣言前にアクセスしようとするとエラーが出ます。
JavaScript
console.log(a); // undefined (varの場合、宣言が巻き上げられる)
var a = 100;
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 200;
大きなコードベースでは、複数人の開発者が同じ変数名を使うことがあります。ローカルスコープを使えば、同名の変数を違う関数やブロックで宣言しても問題ありません。
ローカルスコープ内で宣言された変数は外部から直接アクセスできません。例えば、APIキーやトークンなど機密情報を関数の中だけに閉じ込められることで、誤ってグローバルからアクセスされるリスクを減らせます。
変数がどの範囲で使われるかが明確になるため、コードの可読性が上がり、バグの追跡もしやすくなります。
**クロージャ(Closure)**とは、関数が宣言された時点でのスコープを保持し続ける仕組みを指します。JavaScriptでは、関数が生成された際にその関数がアクセスできる変数(親スコープの変数)が内部的に保持されます。これにより、親関数の実行が終了しても、その関数内部で宣言した関数からは引き続き外部(親)の変数にアクセスできます。
JavaScript
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
上記例では、outer
関数の実行が終わっているにもかかわらず、inner
関数はouter
で宣言された変数count
にアクセスできます。これがクロージャの基本的な仕組みです。
クロージャは関数のローカルスコープに宣言された変数をあたかも「生き続けている」かのように参照し続けられる点で、ローカルスコープをより応用的に使うための概念です。本来なら関数終了とともに消えるはずのローカル変数が、内部関数が存在している限りはガーベジコレクション(GC)されないという仕組みになっています。
グローバル変数は便利ですが、大規模プロジェクトでは変数名衝突や意図しない副作用が起きやすくなります。可能な限りlet
やconst
を使ってローカルスコープに変数を閉じ込めることを推奨します。
let
を使って必要最小限のブロックに閉じ込める。const
を使ってブロックに閉じ込める。var
は関数スコープ、let
とconst
はブロックスコープを持ちます。