ホームページ > 記事 > ウェブフロントエンド > 閉鎖とは何ですか
クロージャは、別の関数のスコープ内の変数にアクセスできる関数です。
–《JavaScript高度なプログラミング》
在这个函数fun2中可以访问另一个函数中的变量a,所以fun2()就是一个闭包。 function fun1 () { var a = 0; function fun2 () { console.log(a); } fun2(); }
1.定義した関数の外でclosureメソッドを呼び出す、escapeメソッド:
(1)内部関数をグローバル変数に代入する;
var globalVar; function outer() { console.log(‘outer’); function inner(){ console.log(‘inner’); } globalVar = inner; } outer(); // outer globalVar(); // inner;
の中で例えば、 inner() は、グローバル変数の参照を介して脱出できました。これで、グローバルに呼び出すことができ、outer() の変数を参照できるようになります
(2) 値を返すことで、inner 関数の参照を「救出」します。
function outer() { console.log(‘outer’); function inner(){ console.log(‘inner’); } return inner; } var fn = outer(); // outer fn(); // inner;
この例では、inner()は値を返すことで正常にエスケープし、グローバルに呼び出せるようになり、outer()の変数を参照できるようになりました
2.関数外でクロージャを呼び出すことの影響:増加メモリ使用量;
それは正常です 状況は、関数呼び出しが終了した後、関数の実行環境が環境スタックから離れ、定義された変数が破棄され(破棄はガベージコレクションメカニズムに関連します)、アクティブな変数(変数オブジェクト) が破棄され、メモリが解放されます。しかし、クロージャのスコープ チェーンには外部関数の変数オブジェクトが含まれるため、ガベージ コレクション メカニズムは外部関数の変数と外部関数の変数オブジェクトを再度参照する可能性があります。関数はメモリに保持されます。これにより、メモリ使用量が増加します。
3. クロージャと変数の関係: クロージャでよくある誤解と解決テクニック
クロージャは関数を含む変数オブジェクト全体を保存し、取得される外部オブジェクト変数はクロージャが呼び出された時点のオブジェクト変数です。 、これは外部関数変数の最後の値です。
例:
function createFun() { var result = []; for ( var i = 0; i < 10; i++) { result[i] = function() { return i; }; } return result; } var result = createFun(); console.log(result5); // 10
ここでの外部関数の戻り値は配列であり、その配列値は異なる関数(クロージャ)への参照であると誤解してしまいますが、各クロージャ呼び出しの戻り値は異なります。しかし実際には、各関数は同じ値を返します。クロージャが呼び出されるとき、クロージャを呼び出した外部関数が実行されています。このとき、外部関数の変数オブジェクトでは i = 10 であり、クロージャの戻り値は i であるため、クロージャは外部関数を取得します。呼び出し時の変数オブジェクト、この時点の i は 10 です。
解決策:
function createFun() { var result = []; for ( var i = 0; i < 10; i++) { result[i] = function(num) { return function() { return num; }; }(i); } return result; } var result = createFun(); console.log(result5); // 5
ループ内で匿名配列を定義し、匿名関数を即座に実行した結果をその配列に代入します。ここでの匿名関数にはパラメーター num があり、毎回 i がパラメーターとして渡されます。 num、numがループされるたびに異なる値が取得されるため、毎回異なる関数が返されます(違いは、配列の値が外部から呼び出された場合に異なる値が返されることです)。 、 予想通り。
4. クロージャ内の this の値に注目してください
まず、関数内の this の点ですが、明示的に呼び出しているオブジェクトがない場合、this は関数を呼び出すオブジェクトを指していることを知っておく必要があります。ウィンドウオブジェクトを指します。
クロージャ内のこの点は、例えば:
var name = “window”; var o = { name: “object”, getName: function() { return function() { return this.name; }; } }; console.log(o.getName()()); // window
クロージャ this がグローバル オブジェクトを指していることがわかります。分析すると、o.getName()() を (o.getName) と書くことができます。 ()) () の場合、この式は最初のステップで o.getName() を実行することと同じです。この関数は匿名関数 (クロージャ) を返し、オブジェクト o を通じてグローバルに呼び出されません。グローバルオブジェクトを指します。
5. メモリリークの問題、不要なメモリ使用量を減らす方法
function assignHandler() { var ele = documnet.getElementById(“somenode”); ele.onclick = function() { console.log(ele.id); }; }
上記の例では、eleの定義方法が匿名関数に関係しているので、eleは匿名関数への参照を保存し、クロージャはそれを参照します。 包含関数は ele オブジェクトも参照します。これにより、オブジェクトへの循環参照が発生します。ele 要素 (dom 要素は大量のメモリを占有します) は常にメモリに格納され、解放できません。以下の通り:
rreee
以上が閉鎖とは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。