Javascriptのクロージャを詳しく解説_基礎知識
前書き: これはまだ紹介記事です。 Javascript には、オブジェクト、プロトタイプの継承、クロージャなど、非常に重要な言語機能がいくつかあります。その中でもクロージャは、従来の静的言語 C/C を使用するプログラマ向けの新しい言語機能です。この記事では、JavaScript クロージャの言語機能を紹介する例から始め、それをいくつかの ECMAScript 言語仕様と組み合わせて、読者がクロージャをより深く理解できるようにします。
注: この記事は入門記事であり、サンプル資料はインターネットから収集したものです。専門家であれば、この記事に関する技術的な提案や意見を提供していただけます。この記事では Javascript について説明します。JavaScript に抵抗がある場合は、迂回してください。
クロージャとは
クロージャとはクロージャのことで、静的言語にはない新しい機能です。しかし、クロージャは理解するのが難しいほど複雑なものではありません。つまり、クロージャは次のとおりです。
クロージャは関数のローカル変数のコレクションですが、これらのローカル変数は関数が戻った後も存在し続けます。
クロージャとは、関数が戻った後に関数の「スタック」が解放されないことを意味し、これらの関数スタックはスタック上ではなくヒープ上に割り当てられることも理解できます
。
関数内で別の関数を定義すると、クロージャーが生成されます
上記の 2 番目の定義は、最初の定義の主語、述語、目的語を抽出した最初の補足説明です。クロージャは関数の「ローカル変数」の集合です。このローカル変数は関数が戻った後にアクセスできるというだけです。 (これは正式な定義ではありませんが、クロージャを理解するにはこの定義の方が役立つはずです)
ローカル変数として、関数内のコードからアクセスできます。これは静的言語と変わりません。クロージャとの違いは、関数の実行が終了した後も、関数の外部のコードからローカル変数にアクセスできることです。これは、関数がクロージャを指す「参照」を返すか、この「参照」を外部変数に割り当てて、クロージャ内のローカル変数が外部コードからアクセスできるようにする必要があることを意味します。もちろん、この参照を含むエンティティはオブジェクトである必要があります。JavaScript では、基本型を除いて、その他すべてがオブジェクトであるためです。残念ながら、ECMAScript には、クロージャ内のローカル変数にアクセスするための関連メンバーやメソッドが提供されていません。しかし、ECMAScript では、関数オブジェクトに定義された内部関数 (内部関数) が、この仕組みを通じて、次の方法で外部関数のローカル変数にアクセスできます。
関数 挨拶(名前) {
var text = 'Hello' // ローカル変数
; // 呼び出されるたびにクロージャが生成され、内部関数オブジェクトが呼び出し元に返されます
戻り関数() { アラート(テキスト) }
}
var SayHello=greeting("閉店");
SayHello() // ローカル変数 text
はクロージャを通じてアクセスされます
上記のコードの実行結果は次のようになります: Hello Closure。これは、sayHello() 関数は、挨拶関数の実行後もその中で定義されたローカル変数テキストにアクセスできるためです。
これがクロージャの伝説的な効果です。クロージャには、シングルトン、パワー コンストラクター、クロージャの使用と切り離せない他の Javascript モードなど、JavaScript のさまざまなアプリケーション シナリオとモードがあります。
ECMAScript クロージャ モデル
ECMAScript はクロージャをどのように実装しますか?さらに詳しく知りたい方は、研究用に ECMAScript 仕様を入手してください。ここでは簡単な説明のみを行います。内容もインターネットから入手できます。
ECMAscript スクリプトの関数が実行されている場合、各関数の関連付けには実行コンテキスト シーン (実行コンテキスト) があり、この実行コンテキスト シーンには 3 つの部分が含まれます。
語彙環境
変数環境
このバインディング
3 番目のポイントであるこのバインディングはクロージャとは関係がないため、この記事では説明しません。文法環境は、関数の実行中に使用される変数識別子を解析するために使用されます。文法環境は、環境レコード (環境再コード) と外部参照 (ポインター) という 2 つの重要なコンポーネントを含むオブジェクトとして想像できます。環境レコードには、関数内で宣言されたローカル変数とパラメーター変数が含まれており、外部参照は外部関数オブジェクトのコンテキスト実行シナリオを指します。グローバル コンテキスト シーンにおけるこの参照の値は NULL です。このようなデータ構造は、各参照が外側のコンテキスト シーンを指す一方向リンク リストを形成します。
たとえば、上記の例のクロージャー モデルは次のようになります。sayHello 関数が最下層にあり、上位層が挨拶関数、最外層がグローバル シーンになります。以下に示すように、sayHello が呼び出されると、sayHello はコンテキスト シーンを通じてローカル変数テキストの値を検索するため、画面上のダイアログ ボックスに「Hello Closure」が表示されます。変数環境 (VariableEnvironment) の関数です。と文法環境は基本的に似ています。具体的な違いについては、ECMAScript 仕様ドキュメントを参照してください。
クロージャーのサンプルシーケンス
以前は、JavaScript クロージャとは何か、およびクロージャが Javascript でどのように実装されるかを大まかに理解しました。以下に、いくつかの例を通してクロージャをより深く理解するのに役立ちます。以下に 5 つの例を示します。これらの例は JavaScript Closures For Dummies (ミラー) からのものです。 例 1: クロージャ内のローカル変数はコピーではなく参照です
関数say667() {
// 最終的にクロージャ内に収まるローカル変数
var num = 666;
var SayAlert = function() {alert(num) }
; 番号 ;
SayAlert を返します;
}
var SayAlert = Say667();
SayAlert()
したがって、実行結果は 666 ではなく 667 になるはずです。
例 2: 複数の関数は同じ関数内で定義されているため、同じクロージャをバインドします。
関数 setupSomeGlobals() {
// 最終的にクロージャ内に収まるローカル変数
var num = 666;
// 関数への参照をグローバル変数として保存します
gAlertNumber = function() {alert(num) }
gIncreaseNumber = function() { 数値 }
gSetNumber = function(x) { num = x }
}
setupSomeGlobals(); // 3 つのグローバル変数に値を代入します
gAlertNumber() //666
gIncreaseNumber();
gAlertNumber() // 667
gSetNumber(12);//
gAlertNumber();//12
例 3: ループ内で関数を割り当てる場合、これらの関数は同じクロージャにバインドされます
関数 buildList(リスト) {
var result = [];
for (var i = 0; i
result.push( function() {alert(item ' ' list[i])} );
}
結果を返します;
}
関数 testList() {
var fnlist = buildList([1,2,3]);
// 混乱を避けるためだけに j を使用します - i
を使用することもできます for (var j = 0; j
}
}
testList の実行結果は、item3 の未定義ウィンドウが 3 回ポップアップします。これは、これら 3 つの関数が同じクロージャにバインドされており、item の値が最後の計算結果であるためですが、ループから抜け出すと、 i の値は 4 なので、リスト [4] の結果は未定義です。
例 4: 外部関数のすべてのローカル変数は、この変数が内部関数の定義後に宣言された場合でも、クロージャ内にあります。
関数sayAlice() {
var SayAlert = function() {alert(alice) }
; // 最終的にクロージャ内に収まるローカル変数
var alice = 'こんにちは、アリス';
SayAlert を返します;
}
var helloAlice=sayAlice();
こんにちはアリス();
実行結果は「Hello Alice」のポップアップウィンドウです。ローカル変数が関数sayAlertの後に宣言されている場合でも、ローカル変数には引き続きアクセスできます。
例 5: 関数が呼び出されるたびに新しいクロージャーを作成します
function newClosure(someNum, someRef) {
// 最終的にクロージャ内に収まるローカル変数
var num = someNum;
var anArray = [1,2,3];
var ref = someRef;
戻り関数(x) {
num = x;
anArray.push(num);
alert('num: ' num
'nanArray ' anArray.toString()
'nref.someVar ' ref.someVar);
}
}
Closure1=newClosure(40,{someVar:'クロージャ 1'});
Closure2=newClosure(1000,{someVar:'クロージャ 2'});
クロージャ1(5); // num:45 anArray[1,2,3,45] ref:'someVarクロージャ1'
Closure2(-10);// num:990 anArray[1,2,3,990] ref:'someVar Closure2'
休業の申請
シングルトン:
var singleton = function () {
var privateVariable;
関数 privateFunction(x) {
...privateVariable...
}
戻り値 {
firstMethod: function (a, b) {
...privateVariable...
}、
SecondMethod: 関数 (c) {
...privateFunction()...
}
};
}();
このシングルトンはクロージャを通じて実装されます。プライベート メンバーとメソッドのカプセル化はクロージャによって完了します。匿名の main 関数はオブジェクトを返します。オブジェクトには 2 つのメソッドが含まれており、メソッド 1 はプライベート変数にアクセスでき、メソッド 2 は内部プライベート関数にアクセスできます。注意が必要なのは、匿名 main 関数の最後の「()」です。この「()」がないとシングルトンを生成できません。匿名関数は一意のオブジェクトのみを返すことができ、他の場所から呼び出すことができないためです。これは、クロージャを使用してシングルトンを生成する方法です。

ホット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)

ホットトピック









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

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

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

タイトル: クロージャによって引き起こされるメモリ リークと解決策 はじめに: クロージャは JavaScript における非常に一般的な概念であり、内部関数が外部関数の変数にアクセスできるようにします。ただし、クロージャを誤って使用すると、メモリ リークが発生する可能性があります。この記事では、クロージャによって引き起こされるメモリ リークの問題を調査し、解決策と具体的なコード例を提供します。 1. クロージャによるメモリリーク クロージャの特徴は、内部関数が外部関数の変数にアクセスできることです。つまり、クロージャ内で参照される変数はガベージコレクションされません。不適切に使用すると、

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

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

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

Go 言語の関数クロージャは単体テストで重要な役割を果たします。 値のキャプチャ: クロージャは外側のスコープ内の変数にアクセスできるため、テスト パラメータをキャプチャしてネストされた関数で再利用できます。テスト コードの簡素化: クロージャは値をキャプチャすることで、ループごとにパラメーターを繰り返し設定する必要性を排除し、テスト コードを簡素化します。可読性の向上: クロージャを使用してテスト ロジックを整理し、テスト コードをより明確で読みやすくします。
