ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript クロージャのコードとテキストの詳細かつ簡単な紹介 (Closure)

JavaScript クロージャのコードとテキストの詳細かつ簡単な紹介 (Closure)

黄舟
黄舟オリジナル
2017-03-03 15:37:161155ブラウズ

Closure (クロージャ) は、JavaScript を初歩から深くマスターするための非常に重要な閾値です。これは、JavaScript 言語の難しさであり、多くの高度なアプリケーションがクロージャに依存しているという特徴でもあります。以下に私の勉強メモを書いてください~

シリーズ目次

  • JavaScriptのクロージャを簡単に説明します

  • JavaScriptを簡単に説明します

  • JavaScriptのプロトタイプチェーンと継承を簡単に説明します方法


どこでもクロージャ


フロントエンドプログラミングでは、意図的または非意図的に、直接的または間接的にクロージャを使用することがよくあります。クロージャにより、データ転送をより柔軟にすることができます (一部のクリック イベントの処理など)

!function() {      
  var localData = "localData here";    
     document.addEventListener('click',    //处理点击事件时用到了外部局部变量,比如这里的localData       
        function(){              
           console.log(localData); 
    }); 
}();

別の例は次のとおりです: (とてもフレンドリーですね~~)

!function() {      
  var localData = "localData here";      
  var url = "http://www.baidu.com/";      
  $.ajax({ 
     url : url,          
     success : function() {              
        // do sth...              
        console.log(localData); 
        } 
    }); 
}();

別の例を見てみましょう~~この状況は私たちが通常行うものですcall Closure

function outer() {   
  var localVal = 30;    
  return function(){      
    return localVal;    
  } 
} 
var func = outer();  
func(); // 30

この例では、outer() が呼び出され、無名関数 function() が返されます。この無名関数では、outer() の呼び出しが完了した後に、outer() のローカル変数 localVal にアクセスできます。 func() が再度呼び出されても、outer() のローカル変数 localVal にアクセスできます

クロージャの概念

通常の関数とは異なり、クロージャにより、関数は直接の字句の外で呼び出された場合でも非ローカル変数にアクセスできます範囲。 – Wikipedia

クロージャは、他の関数の内部変数を読み取ることができる関数です。 – Ruan Yifeng

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

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

クロージャの使い方

この部分はこのブログ投稿からの転載です

クロージャはさまざまな場所で使用できます。その最大の用途は 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 は関数の外部で関数内のローカル変数を操作できるセッターと同等です。


Closure-Encapsulation


(function() {   
   var _userId = 23492;   
   var _typeId = 'item';    
   var export = {}; 

   function converter(userId) {          
     return +userId; 
   } 
    export.getUserId = function() {         
       return converter(_userId);     
   } 
   export.getTypeId = function() {          
      return _typeId; 
   }         
   window.export = export;   //通过此方式输出
}());

  export.getUserId(); // 23492 
  export.getTypeId();  // item 
  export._userId;    // undefined  
  export._typeId;    // undefined       
  export.converter; // undefined

クロージャの特性を使用すると、いくつかの複雑な関数ロジックをカプセル化できます。この例では、export メソッド (getUserId、getTypeId) を呼び出して、関数内のプライベート変数に間接的にアクセスします。ただし、export._userId を直接呼び出して _userId を取得することはできません。これは Node でよく使われる機能でもあります~


よくある間違い: ループクロージャー


次のケースでは、値 aaa、bbb、ccc を持つ 3 ps を追加します。 aaa をクリックすると 1 が出力され、bbb をクリックすると 2 が出力され、ccc をクリックすると 3 が出力されます

document.body.innerHTML = "<p id=p1>aaa</p>" + "<p id=p2>bbb</p><p id=p3>ccc</p>";  
for (var i = 1; i < 4; i++) {      
  document.getElementById(&#39;p&#39; + i).         
    addEventListener(&#39;click&#39;, function() {         
    alert(i); // all are 4! 
    });  
}

その結果、aaa、bbb、または ccc をクリックするとすべてalert(4)~~

問題は、値がこの

iは初期化が完了した後のものですその時点ではすでに4です

私たちが望むことを達成するには、aaaをクリックして出力1を、bbbをクリックして出力2を、cccをクリックして出力3を、という手法を使用する必要があります。各ループでは、すぐに実行される匿名関数を使用します。このようにして、alert(i) の値は毎回クロージャ環境の i から取得されます。各ループは 1、2、3 を出力できます

document.body.innerHTML = "<p id=p1>aaa</p>" + "<p id=p2>bbb</p>" + "<p id=p3>ccc</p>";  
for (var i = 1; i < 4; i++) {
  !function(i){ //②再用这个参数i,到getElementById()中引用     
    document.getElementById(&#39;p&#39; + i).       
      addEventListener(&#39;click&#39;, function() {         
      alert(i); // 1,2,3
     });  
  }(i);  //①把遍历的1,2,3的值传到匿名函数里面
}

Thinking question

次の 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のクロージャ(Closure)コードの画像とテキスト、およびその他の関連コンテンツの詳細な紹介です。 PHP 中国語 Web サイト (www.php.cn) に注意してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。