JavaScript の高度なクロージャの説明

JavaScript の高度なクロージャの説明

1. 閉鎖の概念

一般的な機能の実行とインスピレーションを見てみましょう。

        関数stop() {
            var 数値 = 0;
            console.log(数値);
        }
        stop(); // num が 0 であることを出力します
        console.log(num); // エラー報告関数が定義されていません

1. この時点では関数内の変数は関数外からアクセスできない

2. 関数内で定義された変数は常に存在するわけではなく、関数が終了すると消えます。

閉鎖の概念:

1. 別のスコープ内の変数にアクセスできる関数です。

2. 別の言い方をすると、内部関数の有効期間が外部関数の宣言有効期間よりも長く、内部関数が何らかの方法で外部スコープからアクセスされる場合、クロージャが作成されるということです。

次のクロージャ コードと説明を見てみましょう。

        関数fn() {
            var 数値 = 10;
            // 関数 fun() {
            // コンソール.log(数値);
 
            // }
            // fun を返します。
            関数を返す(){
                console.log(数値); // 10
            }
        }
        var f = fn();
        関数f();

これをいくつかの部分に分けることができます。

1. fn 関数は内部の戻り値を持ち、関数です。

2. return 関数は内部の num 変数を出力します。 num 変数が出力できる理由は、スコープ チェーンのアクセス メカニズムによるものです。以下では、スコープとスコープ チェーンの知識ポイントを補足します。

3. f変数を使用してfn()を外部的に受け入れます。つまり、fn[内部関数]の戻り値を受け入れます。

4. 次に f が呼び出されます。これは、fn 内の内部関数が呼び出されることを意味します。最終的に10を印刷できる

追加の知識ポイント:

1. 範囲:

変数は特定の範囲内で動作し、この範囲外では効果がありません。この範囲が範囲です。スコープは関数が呼び出されたときではなく、関数が定義されたときに作成されます。

2. スコープチェーン:

一言でまとめると、「内部関数は外部関数変数にアクセスできる」という考え方に基づき、近接原則を採用して、変数をレイヤーごとに検索します。このメカニズムはスコープ チェーンと呼ばれます。

関数 A に関数 B が含まれている場合、関数 B は関数 A の内部関数になります。

内部関数が変数を使用する場合、まずその内部にそのような変数が存在するかどうかを確認します。

そうでない場合は、次のレベルを検索します。[近接の原則]

関数がレイヤーごとに見つからない場合は、最終的にグローバル変数の下で検索されます。

        var a = 1;
        var b = 11;
        関数fn1() {
            var a = 2;
            var b = '22';
            関数fn2();
            関数fn2() {
                var a = 3;
                関数fn3();
                関数fn3() {
                    var a = 4;
                    コンソールログ(a); // 4
                    console.log(b); // '22'
                }
            }
        }
        関数fn1();

3. ガベージコレクションのメカニズム

JS ガベージ コレクション メカニズムに関するこのビッグ ブラザーの説明を参照できます。

//www.jb51.net/article/229425.htm

これら3つの概念を組み合わせて、閉鎖の役割を見てみましょう。

2. 閉鎖の役割:

関数 A を外部関数と呼び、この関数内に関数 B があります。

関数A [関数B]の戻り値を受け取るために外部で変数fを使用する

関数Aのスコープ内の変数はnumと呼ばれます

1. 関数の外部から関数内の変数にアクセスできるようにする [内部スコープへの外部アクセス用のチャネルを構築する]

原則:実際には上記で説明しました。

まず、上に示した一連の動作の原理を理解する必要があります。関数Bは関数Aの変数numを呼び出すことができる

2 番目に理解すべきことは、まず、関数 A の戻り値は関数 B [内部関数] であり、次に、この戻り値は関数外部の変数 f で受け取られる必要があるということです。それを受け取った後、関数 B を呼び出すことができ、関数 B は関数 A の変数 num にアクセスします。そして、この内部関数 B が閉鎖関数です。

2. 関数内の変数のライフサイクルを延長できます。

最初の効果は 2 番目の効果をもたらします。 js 変数にはガベージ コレクション メカニズムがあります。関数が実行されると、変数はクリアされ、メモリが削除されます。ただし、クロージャが使用されている場合、変数はすぐにクリアされない可能性があります。

その理由は、外部変数 f が関数 A の内部関数 B を受け入れ、この内部関数が関数 A のスコープ内の変数 num にアクセスするためです。関数 B が実行され、変数 f が存在する限り、変数 num は常に存在します。関数 A の実行が終了しても消えることはありません。

非常に詳しく解説されているので、以下の記事も参考にしてください。

JavaScript クロージャの説明

3. 閉鎖例

クロージャのいくつかのアプリケーションは後で追加されます。

クロージャをいつ使用するかを覚えておき、乱用しないようにする必要があります。

3.1 liをクリックすると現在のliのインデックス番号が出力されます。

    <ul class="nav">
        <li>ドリアン</li>
        <li>臭豆腐</li>
        <li>ニシンの缶詰</li>
        <li>大きな豚足</li>
    </ul>
    <スクリプト>
        // クロージャの適用 - li をクリックすると、現在の li のインデックス番号が出力されます // 1. 属性を動的に追加するメソッドを使用できます var lis = document.querySelector('.nav').querySelectorAll('li');
        (var i = 0; i < lis.length; i++) の場合 {
            lis[i].onclick = 関数(){
                console.log(i); // 4 つの 4
            }
        }
    </スクリプト>

原理:上の図をこのように書くと、印刷される i は常に 4 になります。その理由は、この時点では非厳密モードになっているからです。非厳密モードでは、for ループは同期実行タスクですが、ボタンのクリックは非同期タスクです。同期実行が完了すると、i に 4 が加算されます。次に、非同期タスクは i を出力しますが、これは常に 4 です。

解決策1: クロージャを使用する

1. forループは4つの即時実行される関数を生成する

2. 即時に実行される関数はクロージャのアプリケーションです。 [クリック コールバック] 関数を含む即時実行関数内のすべての関数は、即時実行関数によって渡されたパラメータを使用できます。

        (var i = 0; i < lis.length; i++) の場合 {
            (関数 (i) {
                // コンソールログ(i);
                lis[i].onclick = 関数(){
                    コンソールにログ出力します。
 
                }
            })(私);
        }

変更2: var--->let

対応する小さな li をクリックし、対応するインデックス番号である i を印刷します。 letの使用はES6構文であり、forはブロックレベルのスコープを持ちます。

        var lis = document.querySelector('.nav').querySelectorAll('li');
        (i = 0 とします; i < lis.length; i++) {
            lis[i].onclick = 関数(){
                // コンソールログ(i);
                コンソールにログ出力します。
            }
        }

方法3: カスタム属性インデックスを設定する方法を使用する

        var lis = document.querySelector('.nav').querySelectorAll('li');
        for (var i = 0; i < lis.length; i++) { // これはletではなくvarであることに注意してください
            lis[i].index = i; // これはthis.indexではなくlis[i]であることに注意してください。この時点ではクリックは行われていないので、これはどこから来るのでしょうか?
            lis[i].onclick = 関数(){
                コンソールにログ出力します。
            }
        }

要約する

この記事はこれで終わりです。皆さんのお役に立てれば幸いです。また、123WORDPRESS.COM のその他のコンテンツにも注目していただければ幸いです。

以下もご興味があるかもしれません:
  • JSにおけるクロージャの役割について詳しく話しましょう
  • JavaScriptクロージャの原理と機能の詳細な説明
  • JavaScript クロージャの詳細
  • JavaScript クロージャの説明
  • JavaScriptのクロージャとは何かを学びましょう

<<:  HTMLで細い線のテーブルを作成する簡単な例

>>:  ウェブページの背景画像を伸ばす2つの方法

推薦する

React のクラスからフックへの移行

目次リアクトフック序文なぜフックなのか?クラス関数クラスとフックの比較フックはコンポーネントの状態を...

Reactフックとzarmコンポーネントライブラリ構成に基づいてh5フォームページを開発するためのサンプルコード

最近、React Hooks を zarm コンポーネント ライブラリと組み合わせて使用​​し、js...

docker の実行に必要な権限の分析

Docker を実行するには root 権限が必要です。非 root ユーザーに docker コマ...

MySQL 5.7.21 解凍版のインストールと設定方法のグラフィックチュートリアル

私は頻繁にシステムをインストールするので、インストールのたびにいくつかのソフトウェアを再インストール...

nginx をベースにした Web クラスター プロジェクトをすばやく構築する方法を説明します。

目次1. プロジェクト環境2. プロジェクトの説明3. プロジェクトの手順1. インストール2. 構...

JS のあらゆる場所で絶対等価演算子の使用をやめる

目次概要1. NULL値のテスト2. ユーザー入力を読み取る導入事実の根源はどこにあるのでしょうか?...

Vue2.x - アンチシェイクとスロットリングの使用例

目次ユーティリティ: vue での使用:説明する:画像安定化:スロットル:ユーティリティ: // 手...

少なくともn日間連続してログインしているユーザーに対するSQLクエリ

MySQL ツールを使用して、3 日間連続する例を見てみましょう。 1. SQL テーブルを作成しま...

Nginx+Tomcat 負荷分散クラスタの実装例

目次導入1. 事例の概要2. 環境の展開3. Nginxホストのインストール4. Tomcatのイン...

CSS を使用してデータ ホットスポット効果を実現する方法

効果は以下のとおりです。 分析する1. ここでは、点を囲む 3 つの円がズームアニメーションを実行し...

Iframe の内外のページで JS がどのように動作するかの概要

目次iframeの外側のiframeのコンテンツを取得する方法1方法2 iframe 内の ifra...

CSS を使用してテクスチャ付きグラデーション背景画像を記述するためのサンプル コード

プロジェクト内のページの長さはおよそ2000px以上あり、背景画像にはテクスチャやグラデーションがあ...

CSS3 フィルターの違いと応用の詳しい説明:ドロップシャドウフィルターとボックスシャドウ

標準 CSS3 を使用して要素の影の効果を実現するには、2 つの手順があります。1 つ目は一般的なb...

シェルスクリプトによるDockerコンテナの起動順序の制御の詳細な説明

1. 遭遇した問題分散プロジェクトの展開プロセスでは、サーバーの再起動後にアプリケーション(データベ...

MySQL 最適化戦略 (推奨)

要約すれば: 1. データベースの設計とテーブルの作成時にパフォーマンスを考慮する2. SQLの記述...