ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript クロージャの魔法: 明確で簡単なガイド
クロージャーは、授業後に持ち歩くバックパックのようなものだと考えてください。バックパックの中には、授業中に学んだメモや資料がすべて入っています。クラスが終了した後でも、必要なときにいつでもバックパックのすべてにアクセスできます。同様に、クロージャを使用すると、関数は、外部関数の実行が終了し、関数の外部からそれらの変数にアクセスできなくなった後でも、その外部スコープから変数やパラメーターにアクセスし続けることができます。
上記の説明はクロージャを説明する一般的な方法ですが、JavaScript を初めて使用する人にとっても初心者向けでしょうか?あまり。私も初めて遭遇したときはかなり戸惑いました。そのため、クロージャをできるだけ簡単に誰でも理解できるようにするためにこの記事を書きました。トピックを深く掘り下げる前に、まず基本を説明します。
クロージャとは何かを理解するには、JavaScript のスコープを簡単に見てみる必要があります。スコープとは、コードのさまざまな部分にある変数と関数のアクセス可能性を指します。これにより、プログラム内の特定の変数または関数にアクセスできる場所が決まります。
スコープには、グローバル スコープとローカル スコープという 2 つの主なタイプがあります。グローバル スコープで宣言された変数は関数またはブロックの外側に存在するため、コード全体からアクセスできます。対照的に、関数またはブロック内などのローカル スコープで宣言された変数は、その特定の関数またはブロック内でのみアクセスできます。以下のコードは、この説明を示しています。
// GLOBAL SCOPE let myName = "John Doe"; function globalScope() { console.log(myName); } globalScope(); //Output John Doe console.log(myName); // Accessible here as well // LOCAL SCOPE function localScope() { let age = 30; console.log(age); } localScope(); //Output 30 console.log(age); //Output age is not defined (Not Accessible)
ただし、JavaScript は字句スコープとして知られる概念を使用します。これは、クロージャがどのように機能するかを理解するために重要です。字句スコープとは、変数へのアクセス可能性がコード作成時のコードの構造によって決定されることを意味します。簡単に言うと、「変数が関数内で宣言されている場合、その関数とその関数内にあるものだけがその変数にアクセスできます。」{https://javascript.info/closure}.
これをより明確に理解するために、JavaScript が舞台裏でどのように動作するかを見てみましょう。 JavaScript は、実行コンテキストと呼ばれるものを使用します。これは、実行されるコードを保持するコンテナのようなものです。変数、関数、およびコードのどの部分が現在実行されているかを追跡します。スクリプトが開始されると、グローバル実行コンテキスト (GEC) が作成されます。プログラムにはグローバル実行コンテキストが 1 つだけ存在することに注意することが重要です。
上の図は、プログラム開始時のグローバル実行コンテキストを表しています。これは、作成 (または記憶) フェーズと実行 (またはコード) フェーズの 2 つのフェーズで構成されます。作成フェーズでは、変数と関数がメモリに保存されます。変数は未定義として初期化され、関数は完全に保存されます。実行フェーズでは、JavaScript がコードを 1 行ずつ実行し、変数に値を代入し、関数を実行します。
JavaScript が実行コンテキストと字句スコープをどのように処理するかを理解したので、これがどのようにクロージャに直接結びつくのかがわかります。
JavaScript のクロージャは、外部関数の実行が終了した後でも、内部関数が外部関数のスコープ内の変数へのアクセスを保持しているときに作成されます。これが可能になるのは、内部関数が定義された字句環境を保持し、外部スコープの変数を「記憶」して使用できるようにするためです。
// GLOBAL SCOPE let myName = "John Doe"; function globalScope() { console.log(myName); } globalScope(); //Output John Doe console.log(myName); // Accessible here as well // LOCAL SCOPE function localScope() { let age = 30; console.log(age); } localScope(); //Output 30 console.log(age); //Output age is not defined (Not Accessible)
ここでは、上記のコードがどのように機能するかについてのガイドを示します。関数を呼び出すたびに、JavaScript エンジンはその関数に固有の関数実行コンテキスト (FEC) を作成します。これはグローバル実行コンテキスト (GEC) 内に作成されます。 GEC とは異なり、プログラム内に複数の FEC を含めることができます。各 FEC は独自の作成フェーズと実行フェーズを経て、独自の変数環境と語彙環境を持ちます。字句環境により、関数は外部スコープから変数にアクセスできるようになります。
outerFunction が呼び出されると、新しい FEC が作成されます。outerFunction 内で、字句スコープにより externalVariable にアクセスできる innerFunction を定義します。 externalFunction が戻った後、outerFunction の実行コンテキストはコール スタックから削除されますが、innerFunction はクロージャのため、outerVariable へのアクセスを保持します。したがって、後でクロージャサンプル() を呼び出すと、outerFunction が完了した場合でも、outerVariable をログに記録できます。
次の例を見てみましょう:
Let’s look at the example below: function outerFunction() { let outerVariable = 'I am John Doe'; return function innerFunction() { console.log(outerVariable); }; } const closureExample = outerFunction(); closureExample(); // Outputs: "I am John Doe"
このコードの出力は何になると思いますか?多くの人は 5 を推測したかもしれませんが、それは本当に正しい出力なのでしょうか?実際には、いいえ、その理由は次のとおりです。関数 y() は、変数 a を参照しており、その初期値は参照していません。 z() が呼び出されると、内部関数を返す前に更新が行われたため、a の現在の値 (50) が記録されます。別の例を見てみましょう:
function x(){ let a = 5 function y(){ console.log(a) } a = 50 return y; } let z = x(); console.log(z) z();
コードはクロージャの力を示しています。最も内側の関数 z() でも、親スコープから変数にアクセスできます。ブラウザを調べて [ソース] タブを確認すると、x と y の両方でクロージャが形成されていることがわかります。これにより、z() は親コンテキストから a と b にアクセスできるようになります。
クロージャは、特により柔軟でモジュール化された保守可能なコードを作成する場合に、JavaScript にいくつかの利点をもたらします。以下に主な利点をいくつか示します:
1.コールバック関数: クロージャは、コールバック、イベント リスナー、Promise などの非同期プログラミングを扱う場合に非常に強力です。これらにより、コールバック関数は、外部関数が完了した後でも、外部関数からの変数へのアクセスを維持できるようになります。
// GLOBAL SCOPE let myName = "John Doe"; function globalScope() { console.log(myName); } globalScope(); //Output John Doe console.log(myName); // Accessible here as well // LOCAL SCOPE function localScope() { let age = 30; console.log(age); } localScope(); //Output 30 console.log(age); //Output age is not defined (Not Accessible)
2.モジュール性と保守性: クロージャは、開発者がより小さく再利用可能なコードのチャンクを記述できるようにすることでモジュール性を促進します。クロージャは関数呼び出し間で変数を保持できるため、反復ロジックの必要性が減り、保守性が向上します。
3.グローバル変数の回避: クロージャはグローバル変数の必要性を減らすのに役立ち、潜在的な名前の競合を回避し、グローバル名前空間をクリーンに保ちます。クロージャを使用すると、データをグローバルではなく関数スコープに保存できます。
クロージャは JavaScript の強力な概念であり、関数が実行された後でも外部スコープから変数を記憶してアクセスできるようにすることで、関数の機能を拡張します。この機能は、特に非同期タスク、コールバック、イベント リスナーを処理する場合に、よりモジュール化された柔軟で効率的なコードを作成する際に重要な役割を果たします。クロージャは最初は複雑に思えるかもしれませんが、クロージャをマスターすると、より洗練され最適化された JavaScript を作成できるようになります。練習を続けると、クロージャがよりクリーンで保守しやすいアプリケーションを作成するのにどのように役立つかがわかります。実験を続ければ、すぐにクロージャが JavaScript ツールボックスの自然な部分になるでしょう。
以上がJavaScript クロージャの魔法: 明確で簡単なガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。