閉鎖のjs--焦点1

  異なる視点異なる解釈閉鎖の異なる人々が、それぞれ、3つの権威ある説明があります。

    関数とその字句環境参照は、閉鎖を構成します。言い換えれば、クロージャは、JavaScript関数が毎回作成されるクロージャを生成する内部関数から外部関数のスコープにアクセスすることができます。--MDN

    関数が覚えて、すべてのレキシカルスコープにアクセスすることができたとき、それはクロージャを作成します。関数は、現在の域外効果で実行されている場合でも。 - 「あなたは、ボリューム上のJavaScript()を知りません。」

    関数が別の関数スコープの変数へのアクセスが閉鎖されています。 - 「JavaScriptの高度なプログラミング(第3版)」

  私たちは、単に入れ子関数の関数として理解することができる、変数、関数の機能は、父が環境の閉鎖を生じた訪問。

  上記の定義から、その関数クロージャは、三つの特徴を有する:アクセス範囲が配置され、アクションが外部に起動され、ネストされた関数は、内部変数のライフサイクルを延ばします。

  ここでは、最初のガベージコレクションが何であるかを理解する必要があり、変数のライフサイクルは何ですか?

    ライフサイクルは、適切な範囲の存在下で時間変数または関数として見ることができます。変数と人々は、ライフサイクルを持つことになります。定義から、使用するには、変数のライフサイクルではありません。一般的に、ローカル変数のライフサイクルは、関数が実行された後に終了しますが、閉鎖を除きます。グローバル変数はグローバルな使用に宣言された後、それはページの終了後に終了します。変数は既にこの変数は、ガベージコレクション機構のポンプをリサイクルし、そのメモリを解放します取るの生活のサイクルが終わりに近づいている場合。

    ガベージコレクション:メモリ変数は、変数の間に存在するが、メモリを解放するために、もはや他の場所で使用される使用していない後にクリアされ、ガベージコレクションは、固定された時点で、定期的に実行されます。

  例:

    < スクリプト> 
        関数FN1(){
             VARのB =  12 
        }
        FN1();
        console.log(B)// bが定義されていない
    </ スクリプト>

  関数FN1内の変数bが実行されているため、なぜ文句を言うだろう、それはもはや他の場所で使用されていない、次のエラー表示Bを出力しますので、変数bを持っていなかった番組が定義されていないことをリサイクルガベージコレクションメカニズムであります。

  例:

    < スクリプト> 
        関数FN2(){
             VAR N =  10 関数FN3(){
                console.log(N)// 10 
            }
            FN3();
        }
        FN2();
    </ スクリプト>

  上記の例から、我々は閉鎖となりFN3見ることができる、それが閉じられたパッケージの3つの機能の機能と一致しています。そのガベージコレクションがないjsの資源回収FN2は、内部関数の変数に依存するFN2 FN3 FN2必要性の実装以来占められているように、我々は、実行された機能のFN2に閉鎖を見ることができます。

  だから我々は、閉鎖のメリットと結論付けることができます:メモリ内の変数を維持するには、キャッシュは、他の環境変数の競合の流入を防止するためにパッケージ化を達成するために内部のセキュリティ機能の変数を保護するために行うことができ、自己実行匿名関数は、内部シャオ消費量を減らすことができます。

  注意を払うする必要があるクロージャを使用して:閉鎖のためには、変数は大量のメモリ消費量に格納され、重症の場合は、ページカトンを引き起こす可能性があります機能します。ですから、すべてのローカル変数を削除する機能を終了する前に、親関数の外側クロージャー、内部変数の親関数の値を変更します。あなたは、そのパブリックメソッド(パブリック・メソッド)の閉鎖として、その私有財産(非公開の値)などの内部変数を使用するオブジェクト(オブジェクト)として親関数を取るのであれば、その後はない何気なくに注意してください親関数の内部変数の値を変更します。

  ループの閉鎖と、次のコードを使用して分析

    < スクリプト> 
        関数createFn(){
             VARの結果=  新しいアレイ()。
            ためVAR iは=  0 ; I <  5 ; I ++ ){
                その結果、[I] =  関数(){
                     戻りIと、
                }
            }
            戻り値の結果;
        }
    </ スクリプト>

  这个函数会返回一个函数数组,表面上看,每个函数都应该返回自己的索引值,以此类推。但实际上每个函数都返回10.因为每个函数的作用域链中都保存着createFn()函数的活动对象,所以它们引用的都是同一个变量i.当createFn()函数返回后,变量i的值是10,此时每个函数都引用着保存变量i的同一变量对象,所以在每个函数内部i的值都是10.与我们想达到的效果不符。此时我们可以通过创建另一个匿名函数强制让闭包的行为符合预期,代码如下:

    <script>
        function createFn() {
            var result = new Array();
            for (var i = 0; i < 10; i++) {
                result[i] = function (num) {
                    return function () {
                        return num;
                    };
                }(i);
            }
            return result
        }
    </script>

  在上面的代码中,定义了一个匿名函数,并将立即执行该匿名函数的结果赋给数组,这里的匿名函数有一个参数num,也就是最终的函数要返回的值,在调用每个匿名函数时,传入了变量i由于函数参数是按值传递的,所以就会将变量i的当前值复制给参数num.而在这个匿名函数内部,又创建并返回了一个访问num的闭包,这样一来,result数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了。

 

 

  

おすすめ

転載: www.cnblogs.com/davina123/p/12012036.html