JavaScript クロージャ
JavaScript の変数はローカル変数またはグローバル変数にできます。
プライベート変数にはクロージャを使用できます。
グローバル変数
関数は関数内部で定義された変数にアクセスできます。例:
関数は関数外部で定義された変数にもアクセスできます。例:
後者のサンプルでは、aはグローバル変数です。
Webページでは、グローバル変数は window オブジェクトに属します。
グローバル変数はページ上のすべてのスクリプトで使用できます。
最初のサンプルでは、aはローカル変数です。
ローカル変数は、それを定義した関数の内部でのみ使用できます。他の関数やスクリプトコードからは利用できません。
グローバル変数とローカル変数は、たとえ名前が同じでも、それらは2つの異なる変数です。一方を変更しても、もう一方の値には影響しません。
![]() |
変数を宣言するときにvarキーワードを使用しない場合、関数内で定義されていても、その変数はグローバル変数になります。 |
|---|
変数のライフサイクル
グローバル変数のスコープはグローバルです。つまり、JavaScriptプログラム全体を通して、グローバル変数はどこでも利用できます。
一方、関数内部で宣言された変数は、関数内部でのみ有効です。これらの変数はローカル変数であり、スコープは局所的です。関数のパラメータも局所的であり、関数内部でのみ有効です。
カウンターのジレンマ
いくつかの数値をカウントしたいとします。そして、そのカウンターがすべての関数で使用できるとします。
グローバル変数を使用して、関数でカウンターをインクリメントできます:
サンプル
試してみる »

カウンターの値は add() 関数の実行時に変化します。
しかし問題は、ページ上のどのスクリプトでも、add() 関数を呼び出さなくてもカウンターを変更できることです。
関数内でカウンターを宣言すると、関数を呼び出さない限りカウンターの値を変更できません:
サンプル
試してみる »

上記のコードは正しく出力されません。add() 関数を呼び出すたびに、カウンターが 1 に設定されるからです。
JavaScript のネスト関数でこの問題を解決できます。
JavaScript ネスト関数
すべての関数はグローバル変数にアクセスできます。
実際、JavaScript では、すべての関数はその1つ上のスコープにアクセスできます。
JavaScript はネスト関数をサポートしています。ネスト関数は1つ上の関数の変数にアクセスできます。
このサンプルでは、ネスト関数plus()は親関数のcounter変数にアクセスできます:
サンプル
試してみる »
外部からplus()関数にアクセスできれば、カウンターのジレンマを解決できます。
また、counter = 0が一度だけ実行されるようにする必要があります。
クロージャが必要です。
JavaScript クロージャ
関数の自己呼び出しを覚えていますか? その関数は何をするでしょうか?
サンプル
試してみる »
サンプル解説
変数addは関数の自己呼び出しの戻り値を受け取ります。
自己呼び出し関数は一度だけ実行されます。カウンターを 0 に設定し、関数式を返します。
add 変数は関数として使用できます。素晴らしい点は、1つ上の関数スコープのカウンターにアクセスできることです。
これは JavaScript のクロージャと呼ばれます。これにより、関数がプライベート変数を持つことが可能になります。
カウンターは匿名関数のスコープによって保護され、add メソッドを通じてのみ変更できます。
![]() |
クロージャはプライベート変数を保護するメカニズムです。関数の実行時にプライベートスコープを作成し、内部のプライベート変数を外部からの干渉から保護します。 直感的に言えば、クロージャは破棄されないスタック環境のようなものです。 |
|---|
