ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript のクロージャを理解する

JavaScript のクロージャを理解する

青灯夜游
青灯夜游転載
2021-02-15 08:59:492939ブラウズ

JavaScript のクロージャを理解する

クロージャ (クロージャ) は Javascript 言語の難しさと特徴であり、高度なアプリケーションの多くはクロージャに依存しています。

1. 変数のスコープ

クロージャを理解するには、まず Javascript の特殊な変数スコープを理解する必要があります。

変数のスコープは、グローバル変数とローカル変数の 2 種類にすぎません。

JavaScript 言語の特別な点は、グローバル変数を関数内で直接読み取ることができることです。

var n=999;
 
  function f1(){
    alert(n);
  }
 
  f1(); // 999

一方、関数内のローカル変数は関数外から読み取ることはできません。

function f1(){
    var n=999;
}
 
alert(n); // error

ここで注意すべき点が 1 つあり、関数内で変数を宣言する場合は、var コマンドを使用する必要があります。これを使用しない場合、実際にはグローバル変数を宣言していることになります。

function f1(){
    n=999;
  }
 
  f1();
 
  alert(n); // 999

2. ローカル変数を外部から読み取るにはどうすればよいですか?

さまざまな理由により、関数内でローカル変数を取得する必要がある場合があります。ただし、前述したように、これは通常の状況では不可能であり、回避策によってのみ実現できます。

つまり、関数内に別の関数を定義するということです。

function f1(){
 
    var n=999;
 
    function f2(){
      alert(n); // 999
    }
 
  }

上記のコードでは、関数 f2 が関数 f1 の中に含まれていますが、このとき、f1 内のすべてのローカル変数が f2 から見えます。ただし、その逆は機能せず、f2 内のローカル変数は f1 からは見えません。これは Javascript 言語特有の「チェーン スコープ」構造で、子オブジェクトはすべての親オブジェクトの変数をレベルごとに検索します。したがって、親オブジェクトのすべての変数は子オブジェクトから見えますが、その逆はありません。

f2 は f1 のローカル変数を読み取ることができるので、f2 を戻り値として使用する限り、f1 の外部でその内部変数を読み取ることはできないでしょうか。

function f1(){
 
    var n=999;
 
    function f2(){
      alert(n); 
    }
 
    return f2;
 
  }
 
  var result=f1();
 
  result(); // 999

3. クロージャの概念

前のセクションのコードの f2 関数はクロージャです。

さまざまな専門文献における「クロージャ」の定義は非常に抽象的で、理解するのが困難です。私の理解では、クロージャーは他の関数の内部変数を読み取ることができる関数です。

JavaScript 言語では、関数内のサブ関数のみがローカル変数を読み取ることができるため、クロージャは単純に「関数内で定義された関数」として理解できます。

つまり、本質的に、クロージャは関数の内部と関数の外部を接続する橋です。

4. クロージャーの使用

クロージャーはさまざまな場所で使用できます。最大の用途は 2 つあり、1 つは前述したように関数内の変数を読み取ること、もう 1 つはこれらの変数の値をメモリに保持することです。

この文をどう理解すればよいでしょうか?以下のコードを見てください。

function f1(){
 
    var n=999;
 
    nAdd=function(){n+=1}
 
    function f2(){
      alert(n);
    }
 
    return f2;
 
  }
 
  var result=f1();
 
  result(); // 999
 
  nAdd();
 
  result(); // 1000

このコードでは、result は実際にはクロージャ f2 関数です。これは 2 回実行され、1 回目の値は 999、2 回目の値は 1000 でした。これは、関数 f1 のローカル変数 n が常にメモリに格納され、f1 が呼び出された後に自動的にクリアされないことを証明しています。

なぜそうなるのでしょうか?その理由は、f1 が f2 の親関数であり、f2 がグローバル変数に割り当てられているため、f2 は常にメモリ内に存在し、f2 の存在は f1 に依存するため、f1 は常にメモリ内にあり、削除されないためです。呼び出しが完了すると、ガベージ コレクション メカニズム (ガベージ コレクション) によってリサイクルされます。

このコードでもう 1 つ注目すべき点は、「nAdd=function(){n =1}」という行です。まず第一に、var キーワードは nAdd の前に使用されていないため、nAdd はグローバル変数です。ローカル変数よりも。次に、nAdd の値は匿名関数であり、この匿名関数自体もクロージャであるため、nAdd は関数の外部で関数内のローカル変数を操作できるセッターと同等です。

5. クロージャ使用時の注意点

1) クロージャは関数内の変数をメモリ上に格納するため、メモリ消費量が非常に多くなります。そのため、クロージャを悪用することはできません。悪用すると、Web ページでパフォーマンスの問題が発生したり、IE でメモリ リークが発生したりする可能性があります。解決策は、関数を終了する前に、未使用のローカル変数をすべて削除することです。

2) クロージャは、親関数内の変数の値を親関数の外で変更します。したがって、親関数をオブジェクトとして使用し、クロージャをそのパブリック メソッドとして使用し、内部変数をプライベート値として使用する場合は、親関数内の変数の値を自由に変更しないように注意する必要があります。

6. 考慮すべき質問

次の 2 つのコードの結果を理解できれば、クロージャの動作メカニズムを理解できるはずです。

コード スニペット 1

var name = "The Window";
 
  var object = {
    name : "My Object",
 
    getNameFunc : function(){
      return function(){
        return this.name;
      };
 
    }
 
  };
 
  alert(object.getNameFunc()());

コード スニペット 2

var name = "The Window";
 
  var object = {
    name : "My Object",
 
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
 
    }
 
  };
 
  alert(object.getNameFunc()());

プログラミング関連の知識の詳細については、プログラミング入門をご覧ください。 !

以上がJavaScript のクロージャを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。