この記事の内容は、JS クロージャとその関数についての深い理解を共有することです。必要な友人はそれを参照できます。このコードには 2 つの特徴があります。 1. b 関数 a 内に埋め込まれたセット
2. 関数 a は関数 b を返します。参照関係は図のとおりです:
このように、var c=a() を実行すると、変数 c は実際には関数 b を指します。 c() を実行すると、次のウィンドウが表示されます。 i の値を表示します (最初の回数は 1)。このコードは実際にクロージャを作成します。なぜでしょうか。関数aの外側の変数cが関数a内の関数bを参照しているため、つまり、
もっと徹底しましょう。いわゆる「クロージャ」とは、コンストラクタ本体内に別の関数を対象オブジェクトのメソッド関数として定義し、そのオブジェクトのメソッド関数が外側の関数本体内の一時変数を参照することです。これにより、ターゲット オブジェクトが存続期間中常にそのメソッドを維持できる限り、元のコンストラクター本体で使用される一時変数の値を間接的に維持できます。最初のコンストラクター呼び出しが終了し、一時変数の名前が消えていますが、変数の値はターゲット オブジェクトのメソッド内で常に参照でき、このメソッドを介してのみ値にアクセスできます。同じコンストラクターが再度呼び出された場合でも、新しいオブジェクトとメソッドのみが生成され、新しい一時変数は最後の呼び出しから独立した新しい値にのみ対応します。 2. クロージャの機能は何ですか?
クロージャと関数 a と入れ子関数 b の関係をより深く理解したい場合は、関数実行コンテキスト (実行コンテキスト)、アクティブ オブジェクト (呼び出しオブジェクト)、スコープ、スコープ チェーン。これらの概念を説明するために、関数 a の定義から実行までのプロセスを例として取り上げます。
1. が 関数 a を定義すると、js インタープリターは関数 a のスコープ チェーンを の定義時に a が存在する「環境」に設定します。 a がグローバル関数の場合、スコープにはウィンドウ オブジェクトのみが存在します。鎖。 2. 関数 a を実行すると、a は対応する実行コンテキストに入ります。
3. 実行環境を作成するプロセスでは、最初に a にscope属性が追加されます。これはaのスコープであり、その値はステップ1のスコープチェーンです。つまり、a.scope=a のスコープ チェーンです。
4. 次に、実行環境が呼び出しオブジェクトを作成します。アクティブ オブジェクトもプロパティを持つオブジェクトですが、プロトタイプを持たないため、JavaScript コードから直接アクセスすることはできません。アクティブ オブジェクトを作成した後、そのアクティブ オブジェクトを のスコープ チェーンの先頭に追加します。この時点で、a のスコープ チェーンには、a のアクティブ オブジェクトとウィンドウ オブジェクトの 2 つのオブジェクトが含まれています。
5. 次のステップは、関数 a を呼び出すときに渡されるパラメーターを格納する、アクティブなオブジェクトに argument 属性を追加することです。
6. 最後に、関数 a のすべての仮パラメータと内部関数 b への参照を a のアクティブ オブジェクトに追加します。このステップでは関数 b の定義が完了したので、ステップ 3 と同様に、関数 b のスコープチェーンを b が定義されている環境、つまり a のスコープに設定します。
これで関数a全体の定義から実行までのステップが完了しました。このとき、a は関数 b の参照を c に返し、関数 b のスコープ チェーンには関数 a のアクティブ オブジェクトへの参照が含まれます。これは、b が a で定義されたすべての変数と関数にアクセスできることを意味します。関数 b は c によって参照されており、関数 b は関数 a に依存しているため、関数 a は復帰後に GC によってリサイクルされません。
関数bを実行すると上記と同じになります。したがって、実行中の b のスコープ チェーンには、次の図に示すように、b のアクティブ オブジェクト、a のアクティブ オブジェクト、ウィンドウ オブジェクトの 3 つのオブジェクトが含まれます。
図に示すように、関数 b で変数にアクセスすると、この時点で
1. 最初にそれ自体のアクティブなオブジェクトを検索し、存在しない場合は戻り、関数 a のアクティブなオブジェクトを検索し、存在するまで順番に検索します。見つかった。
2. 関数 b にプロトタイプのプロトタイプ オブジェクトがある場合、関数 b は、自身のアクティブなオブジェクトを検索した後、最初に独自のプロトタイプ オブジェクトを検索し、その後検索を続けます。これは、JavaScript の変数検索メカニズムです。
3. スコープチェーン全体で見つからない場合は、unknown が返されます。
要約すると、この段落では関数の定義と実行という 2 つの重要な単語について説明します。この記事では、関数のスコープは関数の実行時ではなく定義時に決定されると述べています (手順 1 と 3 を参照)。コードの一部を使用して、この問題を説明します。
function f(x) { var g = function () { return x; } return g; } var h = f(1); alert(h());
· 関数 h のスコープが、alert(h()) の実行によって決定されると仮定すると、このときの h のスコープ チェーンは、 h のアクティブ オブジェクト ->alert のアクティブ オブジェクト -> window オブジェクトになります。
· 関数 h のスコープが定義時に決定されると仮定すると、つまり、h が指す匿名関数のスコープは定義時に決定されます。実行中、h のスコープ チェーンは、h のアクティブ オブジェクト -> f のアクティブ オブジェクト -> ウィンドウ オブジェクトになります。
最初の仮定が真の場合、出力値は未定義です。2 番目の仮定が真の場合、出力値は 1 です。
実行結果は 2 番目の仮定が正しいことを証明し、関数のスコープが実際に関数の定義時に決定されることを示しています。
関数内の変数の安全性を保護します。最初の例を例にとると、関数 a の i には関数 b によってのみアクセスでき、他の手段ではアクセスできないため、i のセキュリティは保護されます。
1. 変数をメモリ内に保持します。前の例と同様に、クロージャにより、関数 a の i は常にメモリ内に存在するため、c() が実行されるたびに、i は 1 ずつインクリメントされます。
2. 変数のセキュリティを保護してJSのプライベートプロパティとプライベートメソッドを実装する(外部からアクセスできない)
プライベートプロパティとプライベートメソッドはコンストラクタの外部からアクセスできない
function Constructor(...) { var that = this; var membername = value; function membername(...) {...} }
以上の3点がクロージャの最も基本的な応用です。シナリオ、多くの古典的なケースはこれに由来します。
Javascript では、オブジェクトが参照されなくなった場合、そのオブジェクトは GC によってリサイクルされます。 2 つのオブジェクトが相互に参照し、サードパーティによって参照されなくなった場合、相互に参照している 2 つのオブジェクトもリサイクルされます。関数 a は b によって参照され、b は a の外側の c によって参照されるため、関数 a は実行後にリサイクルされません。
JavaScript クロージャーを理解することは、その解釈と操作メカニズムを理解することによってのみ、より安全で洗練されたコードを作成することができます。
以上がjs クロージャとその機能についての深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。