クローズド構造モジュール(ベース編)——Object-Oriented Javascriptの3つを使用します.

9662 ワード

なぜモジュール化するのですか?
この問題を聞いたら、こう答えます.
もしあなたが大域変数に失敗したことがないなら、回り道してください.
もしあなたが長い間コードで悪夢を見たことがないなら、新春を楽しく過ごして、早く無事に家に帰ります.
もしあなたがコードを優雅に組み立てることにこだわることがなかったら、回顧してください.下を見ないでください.
 
モジュールの基本思想は、複雑でばらばらなものを、単純で独立した全体に構築することである.デスクトップパソコン、ノートパソコン、iPadは、電子計算素子を統合した古典的な「モジュール」です.彼らの内部にいくつのDトリガーが使われているかは気にせず、いくつかのダイオードを使っています.マウスキーボードやタッチパネルで快適な体験を楽しむだけでいいです.デスクトップパソコン、ノートパソコン、iPadは、同じ電子製品のモジュールですが、よりシンプルで、より人気があります.モジュール化は想像力と創造力の仕事であり、追求さえあれば、いつもより美しいモジュールを作り出します.本稿では、筆者の一番好きなモジュール化のコースを紹介し、読者の批判を受けて、より多くの人のモジュール化のインスピレーションを引き出したいと思います.
 
以下は本題に入ります. 
 ディレクトリ:
理解:三つの作用領域
理解:閉鎖=作用ドメインの私有性+作用ドメインの持続性
実践:クローズドを使って簡単なモジュールを作って、一例の工場です.
 
理解:三つの作用領域
javascriptの役割領域は3つあります.一つはglobalで、一つはlocalで、一つはclosureです.chrome debugを使うと、それぞれの作用領域でそれぞれどのような変数が見られますか?一つ目は多く説明しません.ブラウザでglobalのスコープは実はwindowです.第二種類と第三種類は、個人的には関数のスコープだと思います.closureスコープとは、現在実行されている関数の関数スコープに変数が見つかったのではなく、親関数のスコープに変数が見つかりました.親関数が実行されたとしても.
<!DOCTYPE HTML>
<HTML>
 <HEAD>
  <TITLE>3    </TITLE>
 </HEAD>

 <BODY>
  <script>
	var gLanuageName = "javascript";//global   
	function func(){
		var a = 2;
		if(2 === a){
			var b = 3;
		}
		alert(b);//function      b

		var funcDouble = function(){
			return 2 * a;//closure      a
		};
		
		(function(){
			alert(gLanuageName);//global      gLanuageName
		})();

		return funcDouble;
	}
	var funcDouble = func();
	alert(funcDouble());//funcDouble func    ,func     ,         a  。
	alert(gLanuageName);//global     gLanuageName

  </script>
 </BODY>
</HTML>
 
関数のスコープを理解する
次の手順を読んで、結果は何だと思いますか?undefined3?
<script>
	function func(){
		var a = 2;
		if(2 === a){
			var b = 3;
		}
		alert(b);
	}
	func();
  </script>
 
上のコードを見て、javascriptのスコープをjavaのスコープとして理解すれば、bはundefinedです.しかし、プログラムを実行した結果、b==3です.どうしてbは3で、undefinedではないですか?jsのスコープは関数のスコープで、for、if、swtichのキーワードの後の{}は一つのスコープではないので、function()の後の{}は一つのスコープです.プログラムではvar b=3とalert(b)は同じ関数のスコープにありますので、alert(b)は3です.
 
javascriptのスコープはチェーン式のスコープです.
現在のスコープで変数が見つからない場合、親のスコープで変数を検索します.
<script>
	var gLanuageName = "javascript";//global   
	function func(){
		var a = 2;
		if(2 === a){
			var b = 3;
		}
		alert(b);//function      b

		var funcDouble = function(){
			return 2 * a;//closure      a
		};
		
		(function(){
			alert(gLanuageName);//global      gLanuageName
		})();

		return funcDouble;
	}
	var funcDouble = func();
	alert(funcDouble());
	alert(gLanuageName);//global     gLanuageName

</script>
 
上のコードの実行中にチェーン検索の過程を分析します.
1)alert(b)
まず、現在の関数のスコープで変数bを検索します.結果が見つかり、戻ります.
2)return 2*a
まず、現在の関数のスコープで変数bを検索しましたが、見つかりませんでした.親関数のスコープで検索したら、見つけられました.
3)(function(){alert}
まず、現在の匿名関数のスコープで変数gLanuagNameを検索しましたが、ヒットしませんでした.
上の階の父親関数のスコープを探しましたが、見つけられませんでした.
そして、前の階のglobalスコープで検索したら、結果が見つかりました.
 
明らかに、上へ検索する階層が多いほど、消費時間が長くなります.例えばgLanuagNameを検索すると3つの作用領域を検索してやっと変数を見つけました.効率を上げるために、現在のスコープでよく使われている変数を現在のスコープに入れます.例えばwindow、undefinedなどです.本例では、gLanuagNameをFnc(){}作用域に置いて、一次検索機能領域の消費を減らすことができる.
 
jsをもっとうまくすれば、スコープを変数の形にすることができます.そうすれば、開発者が直接にスコープに訪問して、チェーン検索の消耗を免除することができます.例えばglobal['gLanuage Name],closure.funcName.''a'.ブラウザでは、globalはwindowに相当します.
 
理解:閉鎖=作用ドメインの私有性+作用ドメインの持続性
閉包とは何ですか?そう聞かれるたびに、心が虚ろになります.これは不思議な概念で、失敗の概念です.
私の理解では、閉込め=作用ドメインの恒久性+作用ドメインの私有性です.
 
スコープの持続性
関数が実行された後も、スコープ内のオブジェクト(変数/関数)が保持されていれば、スコープは関数の実行完了に伴って消失しません.クローズドはクローズドというより、スコープの耐久性です.
 
スコープの私有性
プライベート性はよく分かりますが、JSのスコープはチェーンルックで決まります.チェーン検索の方式は、各関数がすべての作用領域にアクセスできる変数ではないことを決定しています.次の手順に示すように、scopeB、scopeCは、連鎖的にScopeAを検索して、a変数にアクセスできます.しかし、scopeBはChopeCにチェーン検索できません.つまり、scopeB関数の内部ではc変数にアクセスできません.ScropeBの下の変数は、ScropeCに対しては見えません.「プライベート」です.
<script>
    function scopeA(){
          var a = 1;
          function scopeB(){
                var b =2;
                var _a = a;
                var getA = function(){
                      return _a;
                }
          }
          function scopeC(){
                 var c = 3;
            }
    }
</script>
 
クローズド=スコープの耐久性+ 
スコープのプライベート性=>モジュールパッケージ
耐久性は、変数の一部を永続的に保存することを可能にします.プライベートプライベートは変数を特定の関数にのみ暴落させることができます.二つの組み合わせは、オブジェクトに向けた「パッケージ」の基礎となります.閉鎖は実現です
モジュールパッケージの利器!
実践:閉包を使ってモジュールを作り、一例工場
次は、Counterの例を示します.このCounterの初期値は0であり、addによって+1を実現することができ、subによって-1を実現し、getによって現在の値、内部の状態データiを取得し、クローズドによって完璧にカプセル化した.外部プログラムはsub、add、getを操作できるほか、i自体を操作できなく、モジュールの安全と安定を確保した.
カウンタープログラム
<!DOCTYPE HTML>
<HTML>
 <HEAD>
  <TITLE>Counter</TITLE>
 </HEAD>

 <BODY>
<script>
		var oCounter = (function(){
			var i = 0;
			var get = function(){
				return i;
			}
			var add = function(){
				i++;
				return i;
			}
			var sub = function(){
				if(i-1<0){
					alert("counter is zero. Cannot perform subtraction.");
					return i;
				}
				i--;
				return i;
			}
			var o = {
				get : get,
				add : add,
				sub : sub
      			};
			return o;
		})();
		oCounter.add();
		alert(oCounter.get());
		oCounter.sub();
		alert(oCounter.get());
		oCounter.sub();
		alert(oCounter.get());
</script>
 </BODY>
</HTML>
  
クローズド定義モジュールを使うと簡単なコースがあります.
1. 「プライベート」「スコープ」として関数を定義します.
2. 関数では、varを使用していくつかの「プライベート」の変数/関数を定義します.
3. 関数を返します
これらを参照してください.
このコースによって、ほとんどのモジュール化の需要を満たすことができます.
 
Counterプログラムは、クローズドの他に、関数が戻ってくるオブジェクトoを明確に記述しています.オブジェクトoは、外部に公開されているインターフェースを明確に説明しています.具体的な実装を隠しています.また、簡単に代替実現できることも意味しています.後の需要が変化したら、subはiをマイナスに減らすことができます.sub 2方法を追加して実現します.修正対象oは
var o = {
    get : get,
    add : add,
    sub : sub2
}; 
このように、oCounterのclientコードを使って変更する必要がないです.JAVAのインターフェース向けプログラミングの味がありますか?「シンプルな考え方は、決まったものではない.
 
上のコードがインターフェースに向かないと思ったら、対象に向かないです.以下のコードを見てください.工場の一例モデルを実現して、パラメータによって異なるカウンターに戻ります.
 
 
<!DOCTYPE HTML>
<HTML>
 <HEAD>
  <TITLE> Counter      </TITLE>
 </HEAD>

 <BODY>
<script>
		//    
		var oCounterFactory = (function(){
			var map = {};
			var oCounter = null;
			
			//    ,          Counter  ,couterType "Counter1"  "Counter2"
			function getSingletonCounter(couterName){
        			//    
				if(null == map[couterName]){
          				//        
					map[couterName] = eval('create' + couterName + '()');
				}
				return map[couterName];
			}

			//    1
			function createCounter1(){
				alert("create oCounter1");
				var i = 0;
				var get = function(){
					return i;
				}
				var add = function(){
					i++;
					return i;
				}
				var sub = function(){
					if(i-1<0){
						alert("counter is zero. Cannot perform subtraction.");
						return i;
					}
					i--;
					return i;
				}
				
				var o = {
					get : get,
					add : add,
					sub : sub
				};

				return o;
			}
			//    2
			function createCounter2(){
				alert("create oCounter2");
				var i = 0;
				var get = function(){
					return i;
				}
				var add = function(){
					i++;
					return i;
				}
				var sub2 = function(){
					i--;
					return i;
				}
				
				var o = {
					get : get,
					add : add,
					sub : sub2
				};

				return o;
			}
		
			var oCounterFactoryRtn = {
				getSingletonCounter : getSingletonCounter
			};
			return oCounterFactoryRtn;
		 })();
				
			
		alert("oCounter1 add : " + oCounterFactory.getSingletonCounter("Counter1").add());
		alert("oCounter1 add : " + oCounterFactory.getSingletonCounter("Counter1").add());
		alert("oCounter1 add : " + oCounterFactory.getSingletonCounter("Counter1").add());
		alert("oCounter2 add : " + oCounterFactory.getSingletonCounter("Counter2").add());
		alert("oCounter2 add : " + oCounterFactory.getSingletonCounter("Counter2").add());
		alert("oCounter2 add : " + oCounterFactory.getSingletonCounter("Counter2").add());
</script>
 </BODY>
</HTML>
  JSはクラスのキーワードがないが、モジュールをうまくカプセル化したり、デザインモードを適用したりすることができます.
 
>>次のページ  クローズド構造モジュールを使用する(最適化編)——Object-Oriented Javascriptの4