JavaScriptのクローズドと高次関数(一)

5502 ワード

ここをクリックして私のgithubを訪問してもっと詳しいことを知ります.
JavaScriptは、表面からオブジェクトに向けたプログラミング言語であるが、Lambada式、クローズド、高次関数などの関数的プログラミングの特性も多い.
関数プログラミングはプログラミングの範式で、コンピュータの演算を関数として計算します.関数プログラミング言語の最も重要な基礎はλ 演算子.しかもλ演算の関数は、入力(パラメータ)と出力(戻り値)として関数を許容できます.
包みを閉じる
クローズドとは何ですか?クローズドの位置についてはそれぞれ自分の意見があります.ここでは、クローズドとは、その外部作用領域にアクセスする変数とパラメータの関数を指します.最も一般的なのは、ある関数の内部に別の関数を作成することです.

    var count = (function() {
        var item = 0;
        
        return {
            add: function(num) {
                item += typeof num === 'number' ? num : 1;
            },
            value: function() {
                return item;
            }
        }
    })();
ここで関数が返した結果をcountに割り当てます.この関数は2つの方法を含むオブジェクトを返します.オブジェクト内の方法は関数を含む変数やパラメータにアクセスできます.countに保存されているのはオブジェクトの参照です.オブジェクト内の方法はまだ実行関数からの変数にアクセスできます.変数自体にアクセスします.
クローズド関数は、作成時のコンテキスト環境の変数およびパラメータ、thisおよびargmentsを除くことができます.
クローズドバックは、実際にはよく説明されていません.私にとって、自己理解と他人に対しての説明は非常に大きな違いがありますが、それを征服してみます.クローズドの形成は変数と密接に関係しています.特に変数の作用と変数のライフサイクルは、詳しく説明してください.
クローズドと変数
クローズドパケットに保存されているのは、変数オブジェクト全体である実行環境(コンテキスト環境)の変数を表すオブジェクトの参照です.実行環境の変数にアクセスすると、変数オブジェクトにアクセスする変数です.
変数オブジェクトは、各実行環境(コンテキスト環境)の中の一つが、すべての変数を表すオブジェクトであり、グローバル環境の変数オブジェクトは常に存在しますが、ローカル環境の変数オブジェクトは、その実行中にのみ存在します.
典型的なケースは以下の通りです.

    function myNumber() {
        var count = [];
        for (var i = 0; i < 10; i ++) {
            count[i] = function() {
                return i;
            }
        }
        return count;
    }
この関数は関数配列を返します.この配列はおとなしく自分の数字に戻りますか?もちろん、実際には各関数は10に戻ります.なぜですか?各関数の作用領域チェーンにはmyNumber()関数の活動対象(変数オブジェクト)が保存されています.彼らは同じ変数のオブジェクトを参照しています.もちろん同じ変数iも参照して、myNumber()関数が戻ってきたらiは10です.
下記のコードを見てください.

    function myNumber() {
        var count = [];
        for (var i = 0; i < 10; i ++) {
            count[i] = (function(num) {
                return function() {
                    return num;
                };
            })(i);
        }
        return count;
    }
ここでは、匿名関数を実行した結果から配列に値を割り当て、各匿名関数を呼び出したとき、変数iに入力され、関数パラメータは値によって伝達され、変数値がパラメータnumにコピーされます.匿名関数の内部ではnumパラメータにアクセスするためのクローズドパケットが作成され、countの関数はすべて自身のnum変数のコピーが保存されています.
変数のスコープ
変数は大域変数と局所変数に分けられ、関数で変数を宣言する場合、varキーワードで定義される変数は局所変数であり、varキーワードを持たないと大域変数になります.
    
    var c = 3
    var func = function() {
        var a = 1;
        b = 2;
        alert(b);//2
        alert(c);//3
    }
    func();
    alert(b);//2
    alert(a);//Uncaught ReferenceError: b is not defined
関数で変数を検索する場合、まず現在の関数で環境作用ドメイン検索を実行します.見つからない場合、現在実行されている環境で作成されているスコープは外部層に検索されます.大域オブジェクトまでは、ここでの検索は内側から外へ検索されます.
変数のライフサイクル
上記の変数の作用領域については、ここで変数のライフサイクルについて説明します.
  • グローバル変数、そのライフサイクルはプログラム全体の実行時間内に永久に存在し、自発的に破壊しない限り、いつでも起動できます.
  • ローカル変数は、所属するスコープコードの実行中に存在し、実行が完了し、外部からこのコンテキスト環境に呼び出された変数が存在しない場合は破壊されます.そうでなければ依然として存在します.
    
        var func = function() {
            var res = [1,2,3,4,5,6];
            var a = 0;
            return function() {
                alert(res[a]);
                a++;
            }
        };
        var f = func();
        
        func()();//1
        func()();//1
        
        f();//1
        f();//2
        f();//3
    
    試し比較実行fun()とf()のポップアップ値は異なり、f()にaがずっと存在しているようです.var f=func()を実行すると、f関数は匿名関数の参照を返します.この匿名関数は、Fnc()が呼び出されたコンテキスト環境(実行環境)にアクセスできます.局所変数とは、その中で、局所変数が置かれている環境が外部に訪問され、局所変数が破壊されないということです.
    閉包の役割
  • カプセル化変数
  • クローズドパッケージは、「プライベート変数」としてパッケージ化できます.例えば、計算積を実現します.
    
        var mult = function() {
            var a = 1;
            for (var i = 0, len = arguments.length; i < len; i++) {
                a = a * arguments[i];
            }
            return a;
        }
        alert(mult(1,2,3,4));
    
  • ブロックレベル作用領域を模仿する
  • JavaScriptには、ブロックレベルのスコープの概念がない.
    
        function block() {
            var res = [1,3,5,7,9];
            for (var i = 0; i < res.length; i++) {
                alert(res[i]);
            }
            var i;//      
            alert(i);//5
        }
    
    上記のコードで見たように、i変数の定義後には、関数全体にわたってアクセスできます.JavaScriptでは、for文はブロックレベルの作用領域を形成しません.その全体の作用領域は関数を含んで作成され、変数に対する後続の宣言は無視されます.ブロックレベルの作用領域効果を達成するためには、クローズドパケットを形成して真似することができます.
    
        (function() {
            //     
        })()
    
  • プライベート変数または関数
  • を追加します.
    プライベートスコープにプライベート変数または関数を定義することにより、プライベートメンバを形成することができます.
    
        (function() {
            var name = 'xjg';
            function getName() {
                reutn name;
            }
            Person = function(val) {
                name = val;
            }
            Person.getName = function() {
                return name;
            }
        })();
        var p1 = new Person('Anagle');
        alert(p1.getName());//Anagle
        alert(getName())//ReferenceError: getName is not defined
    
    ここで、nameは静的なプライベート変数になります.
    クローズドとメモリリーク
    局部変数はもともと関数終了時に破壊されましたが、閉包中はそうではありません.局部変数のライフサイクルが延長されて、閉パックするとこれらのデータが直ちに破壊できなくなり、メモリを占有してメモリが漏れやすくなります.
    
        function addHandle() {
            var element = document.getElementById('myNode');
            element.onclick = function() {
                alert(element.id);
            }
        }
    
    ここでは、Oclick匿名関数は、elementの参照を保存する関数の活動オブジェクト(変数オブジェクト)を含むペアの参照を保存します.elementは回収されません.
    
            function addHandle() {
            var element = document.getElementById('myNode');
            var id = element.id;
            element.onclick = function() {
                alert(id);
            }
            element = null;
        }
    
    ここでelementをnullに設定します.つまり、その引用を解除します.ゴミ回収器はメモリの占有を回収します.
    この文章はJavaScriptに対して締めくくりをして、詳しく述べて、紙面に限られて、次の文章でJavaScriptの中の高次関数を述べます.