JavaScript クロージャとは何かについての深い理解_基礎知識
1. 簡単な例
典型的な間違いから始めましょう。ページには onclick メソッドをバインドしたいので、次のコードがあります。
/span> 2 3
;
;/span> ;2 3
>
コードをコピーします
alert(i);
;
コードをコピー
コードは次のとおりです。
var spans2 = $("#divTest2 span ");
2. 内部関数
基本的な知識から始めて、まず内部関数を理解しましょう。内部関数は、別の関数内で定義された関数です。例:
コードをコピー
function innerFn () { functioninnerFn () {}
}コードは次のとおりです。
function innerFn() {
");
function innerFn() { document.write("内部関数
");
}
ただし、innerFn が externalFn 内で呼び出された場合は、正常に実行できます。
function innerFn() {
document .write( "外部関数
");
function innerFn() {
document.write("内部関数
");
}
innerFn() ;
}
innerFn();
2.1 大脱走
JavaScript を使用すると、開発者はあらゆる種類のデータと同様に関数を渡すことができます。つまり、JavaScript の内部関数は、それを定義する外部関数をエスケープできます。
エスケープする方法は多数あります。たとえば、次のように内部関数をグローバル変数に割り当てることができます。
var globalVar;
function innerFn() {
document.write("Outer function
"); ){
document .write( "Inner Function< br/>");
その後、globalVar を呼び出すことは innerFn を呼び出すことと同じになります。この時点で、innerFn を externalFn の外部で直接呼び出すと、依然としてエラーが発生します。これは、inner 関数は参照をグローバル変数に保存することでエスケープされますが、この関数の名前は依然として externalFn のスコープ内にのみ存在するためです。
親関数の戻り値を通じて内部関数参照を取得することもできます
コードをコピー
コードは次のとおりです。
"); function innerFn() { document.write("内部関数
"); }
var fnRef = innerFn();
fnRef();
グローバル変数は、outerFn 内では変更されませんが、innerFn への参照が、outerFn から返されます。この参照は、outerFn を呼び出すことで取得でき、変数に保存できます。
関数スコープを抜けた後でも内部関数を参照によって呼び出すことができるということは、内部関数を呼び出す可能性がある限り、JavaScript は参照先の関数を保持する必要があることを意味します。さらに、JavaScript ランタイムは、JavaScript ガベージ コレクターが対応するメモリ領域を解放する前に、最後の変数が破棄されるまで、この内部関数を参照するすべての変数を追跡する必要があります (赤い部分がクロージャを理解するための鍵です)。
1.2 変数のスコープ
コードをコピー
コードは次のとおりです:
function innerFn() {
document.write("外部関数
");
document.write(" 内部関数"); }
var fnRef = innerFn();
var fnRef2 = innerFn();
fnRef();
fnRef2();
この内部関数が参照または他の関数によって呼び出されるたびつまり、新しい innerVar 変数が作成され、1 ずつ増分され、最後に
が表示されます。
コードをコピー
コードは次のとおりです。
コードをコピー
コードは次のとおりです:
"); ‐‐‐‐‐‐‐‐‐‐ f(); var fnRef2 = innerFn(); var fnRef2 = innerFn(); fnRef2(); 変数の値:
コードをコピー
コードは次のとおりです。
外部関数
内部関数 globalVar = 1
内部関数 globalVar = 2
外部関数
内部関数 globalVar = 3
内部関数 globalVar = 4
関数 innerFn() {
var externalVar = 0;
document.write("アウター関数
");
innerFn() 関数 {
外側Var ;
document.write("内部関数"); 🎜> }
var fnRef = innerFn();
var fnRef2 = innerFn();
fnRef();
fnRef2();
今回の結果は非常に興味深いもので、おそらく私たちの予想を超えています
コードをコピー
ここで確認できるのは、前の 2 つの効果を組み合わせたものです。 innerFn への各参照呼び出しは、outerVar を個別にインクリメントします。つまり、outerFn への 2 番目の呼び出しは、outerVar の値を引き続き使用せず、2 番目の関数呼び出しのスコープ内に新しい externalVar インスタンスを作成してバインドします。2 つのカウンターはまったく関連しません。
内部関数が定義されているスコープ外で参照されると、内部関数のクロージャが作成されます。この場合、内部関数のローカル変数でもパラメータでもない変数を自由変数と呼び、外部関数の呼び出し環境をクローズドクロージャ環境と呼びます。基本的に、内部関数が外部関数にある変数を参照する場合、その変数の遅延が許可されます。したがって、外部関数の呼び出しが完了しても、これらの変数のメモリは解放されず (最後の値が保存され)、クロージャは依然としてそれらを使用する必要があります。
3. クロージャ間の相互作用
内部関数が複数ある場合、予期しないクロージャが発生する可能性があります。増加関数を定義します。この関数の増分は 2
です。コードをコピー
function innerFn() {
var innerVar = 0;
document.write("Outer function
");
function innerFn1() {
externalVar ;
document.write("内部関数 1t");
document.write("outerVar = " innerVar "
");
}
function innerFn2() {
externalVar = 2;
document.write("Inner function 2t");
document.write("outerVar = " "
") ;
}
return { "fn1": innerFn1, "fn2": innerFn2 };
}
var fnRef = innerFn();
fnRef.fn 1();
fnRef .fn2();
fnRef.fn1();
var fnRef2 = innerFn();
fnRef2.fn1();
fnRef2.fn2();
fnRef2。 fn1() ;
我们射は 2 つの内部関数の参照を返します、表示を介して返される参照を使用できます、結果:
外部関数
内部関数 1 externalVar = 1
内部関数 2 outerVar = 3
内部関数 1 outerVar = 4
外部関数
内部関数 1 outerVar = 1
内部関数 2 outerVar = 3
内部関数 1 outerVar = 4
innerFn1 と innerFn2 は同じ局所的な値を参照するため、どちらも閉鎖的な環境を共有します。 innerFn1 が outerVar になると、innerFn2 は outerVar の新しい開始値を設定します。外部 Fn へのその後の調整は、これらの閉包の新しい例を構築すると同時に、新しい閉包環境も構築します。本質的には、新しいオブジェクトが構築されており、自由量はこのオブジェクトの例の量であり、閉包はこれですオブジェクトの例示的な方法であり、これらの値は、それらをカプセル化する作用領域の外部から直接参照することができないため、対面オブジェクトデータの固有性を確保するために私有のものである。
4.解不安
私たちが見返すことができる、シティ・アラート 4 の例は、毎回シティ・アラート 4 の最初のタイプの書き込み法であることは明らかです。 🎜> 代码如下:
iの値が4の場合、上記コードは判定条件が成立せずforループが実行されますが、各スパンのonclickメソッドは内部関数であるため、今回は、i は閉じられています。参照、メモリは破棄できません。i の値は 4 のままで、プログラムが変更するか、すべての onclick 関数が破棄されるまでリサイクルされません (関数を null にアクティブに割り当てるか、ページがアンロードされます)。 )。このようにして、span をクリックするたびに、onclick 関数は i の値を検索し (スコープ チェーンは参照メソッドです)、それが 4 に等しい場合は警告を発します。 2 番目の方法は、すぐに実行される関数を使用してクロージャーの層を作成する方法です。関数宣言は括弧と括弧を追加した後、式になります。このとき、i はパラメーターとして使用されます。渡されると、関数はすぐに実行され、num は毎回 i の値を保存します。
これを読んだ後は、誰もが私と同じようにクロージャについてある程度理解できるはずです。もちろん、完全に理解した場合は、関数の実行環境とスコープ チェーンを理解する必要があります。^_^

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











顔の検出および認識テクノロジーは、すでに比較的成熟しており、広く使用されているテクノロジーです。現在、最も広く使用されているインターネット アプリケーション言語は JS ですが、Web フロントエンドでの顔検出と認識の実装には、バックエンドの顔認識と比較して利点と欠点があります。利点としては、ネットワーク インタラクションの削減とリアルタイム認識により、ユーザーの待ち時間が大幅に短縮され、ユーザー エクスペリエンスが向上することが挙げられます。欠点としては、モデル サイズによって制限されるため、精度も制限されることが挙げられます。 js を使用して Web 上に顔検出を実装するにはどうすればよいですか? Web 上で顔認識を実装するには、JavaScript、HTML、CSS、WebRTC など、関連するプログラミング言語とテクノロジに精通している必要があります。同時に、関連するコンピューター ビジョンと人工知能テクノロジーを習得する必要もあります。 Web 側の設計により、次の点に注意してください。

C++ では、クロージャは外部変数にアクセスできるラムダ式です。クロージャを作成するには、ラムダ式の外部変数をキャプチャします。クロージャには、再利用性、情報の隠蔽、評価の遅延などの利点があります。これらは、イベント ハンドラーなど、外部変数が破棄されてもクロージャが外部変数にアクセスできる現実の状況で役立ちます。

C++ ラムダ式は、関数スコープ変数を保存し、関数からアクセスできるようにするクロージャーをサポートしています。構文は [キャプチャリスト](パラメータ)->戻り値の型{関数本体} です。 Capture-list は、キャプチャする変数を定義します。[=] を使用してすべてのローカル変数を値によってキャプチャするか、[&] を使用してすべてのローカル変数を参照によってキャプチャするか、[variable1, variable2,...] を使用して特定の変数をキャプチャできます。ラムダ式はキャプチャされた変数にのみアクセスできますが、元の値を変更することはできません。

クロージャは、外部関数のスコープ内の変数にアクセスできる入れ子関数です。その利点には、データのカプセル化、状態の保持、および柔軟性が含まれます。デメリットとしては、メモリ消費量、パフォーマンスへの影響、デバッグの複雑さなどが挙げられます。さらに、クロージャは匿名関数を作成し、それをコールバックまたは引数として他の関数に渡すことができます。

関数ポインタとクロージャが Go のパフォーマンスに与える影響は次のとおりです。 関数ポインタ: 直接呼び出しよりわずかに遅くなりますが、可読性と再利用性が向上します。クロージャ: 一般に遅いですが、データと動作をカプセル化します。実際のケース: 関数ポインターは並べ替えアルゴリズムを最適化でき、クロージャーはイベント ハンドラーを作成できますが、パフォーマンスの低下をもたらします。

js と vue の関係: 1. Web 開発の基礎としての JS、2. フロントエンド フレームワークとしての Vue.js の台頭、3. JS と Vue の補完関係、4. JS と Vue の実用化ビュー。

Java のクロージャを使用すると、外部関数が終了した場合でも、内部関数が外部スコープの変数にアクセスできるようになります。匿名の内部クラスを通じて実装されると、内部クラスは外部クラスへの参照を保持し、外部変数をアクティブに保ちます。クロージャによりコードの柔軟性が向上しますが、匿名の内部クラスによる外部変数への参照により、それらの変数が存続するため、メモリ リークのリスクに注意する必要があります。

はい、コードの単純さと読みやすさは、連鎖呼び出しとクロージャーによって最適化できます。連鎖呼び出しは、関数呼び出しを流暢なインターフェイスにリンクします。クロージャは再利用可能なコード ブロックを作成し、関数の外の変数にアクセスします。
