什麼是閉包?以及閉包的優點,缺點,用處,及特性

定義:閉包 當一個函數的返回值是另外一個函數,而返回的那個函數如果調用了其父函數內部的變量,且返回的這個函數在外部被執行 就產生了閉包.閉包是一個環境,具體指的就是外部函數–高階函數。

    說白了就是一個環境,能夠讀取其他函數內部的變量。

本質上,閉包是將函數內部和函數外部連接起來的橋樑。

用處:1.讀取函數內部的變量;

       2.這些變量的值始終保持在內存中,不會在外層函數調用後被自動清除。

優點:1:變量長期駐紮在內存中;

       2:避免全局變量的污染;

       3:私有成員的存在 ;

特性:1:函數套函數;

       2:內部函數可以直接使用外部函數的局部變量或參數;

       3:變量或參數不會被垃圾回收機制回收 GC;

缺點:

常駐內存 會增大內存的使用量 使用不當會造成內存泄露,詳解:

(1)由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決方法是,在退出函數之前,將不使用的局部變量全部刪除。

(2)閉包會在父函數外部,改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。

var  counter = 10;
		function add () {
			var  counter = 0;
			return function () {
				counter+=1;
				alert(counter)
			}
		}
		
//		var s = add();
		
//		s()// 1
//		s()// 2
//		s()// 3
		
		
		
		function fn () {
			var num = 223;
			var fn1 = function () {
				console.log(num)
			}
			num++;
			return fn1;
		}
		
//		var fn2 = fn()
		
//		fn2()//224
//		fn2()//224
//		fn2()//224
		
//		用途:閉包解決索引值問題
		
		oLi = document.getElementsByTagName("li");
		
		for (var i = 0; i < oLi.length; i++) {			
			/*oLi[i].onclick = function (index) {
				return function () {
					console.log(index)//					
				}
			}(i)*/
			
			(
				function (j) {
					oLi[j].onclick = function () {
						console.log(j)
					}
				}
			)(i)
			
		}
		
//		私有成員的存在
		var  aaa = (function () {
			var a =1 ;
			function bbb () {
				a++;
				console.log(a)
			};
			function ccc () {
				a++;
				console.log(a)
			};
			return {//json結構
				b:bbb,
				c:ccc
			}
		})()
		
//		aaa.b()//2
//		aaa.c()//3
//		aaa.b()//4
//		aaa.c()//5
		
		
		
//		function aaa(a){      
//		      var b = 5;      
//		      function bbb(){
//		           a++;
//		           b++;
////		           debugger   1:斷點調試    2:打斷點
//		         alert(a);
//		         alert(b);
//		      }
//		      return bbb;
//		  }
//		
//		 var ccc = aaa(2);
//		
//		 ccc();
//		 ccc();
 
//		var count = (function(){
//		    var a = 0;
//		    function add(){
//		        a++;
//		        return a;
//		    }
//		
//		    return add;
//		
//		})()
//		
//		count();
//		count();
//		
//		var nowcount = count();
//		
//		alert(nowcount);
 
//		在實際開發中,閉包主要是用來封裝變量,收斂權限    變量的管理方案
		function isFirstLoad(){
            var list=[];
            return function(option){
                if(list.indexOf(option)>=0){ //檢測是否存在於現有數組中,有則說明已存在
                    console.log('已存在')
                }else{
                    list.push(option);
                    console.log('首次傳入'); //沒有則返回true,並把這次的數據錄入進去
                }
                console.log(list)
            }
        }
 
//		var ifl=isFirstLoad();
//		ifl("zhangsan"); 
//		ifl("lisi");
//		ifl("zhangsan");
//		外界想訪問list變量,只能通過我定義的函數isFirstLoad來進行訪問,
//		想訪問list的外界只提供了isFirstLoad這一個接口。至於怎麼操作list,
//		已經定義好了,外界能做的就只是使用函數,然後傳幾個不同的參數
		
		var val=function(){
	        var that=this;
	        var variable={};
	        variable.varity=1;
	        var returnVal={};
	
	        this.isString=function(str){
	             try {
	                if (typeof str !== "string") {
	                    throw "TypeErr";
	                    
	                }else{
	                    return true;
	                }
	            } catch (e) {
	                if (e == "TypeErr") {
	                    return false;
	                }
	            }
	        }
			//讀
	        returnVal.getter=function(str){
	            var isStr=that.isString(str);
	            if(isStr){
	                return variable[str];
	            }else{
	                console.error("input type must string!!!!!");
	            }
	           
	        }
			//寫
	        returnVal.setter=function(key,value){
	            var isStr=that.isString(key);
	            if(isStr){
	                if(variable[key]==undefined){
	                    eval(variable[key]);
	                }
	                variable[key]=value;
	            }else{
	                console.error("input type must string!!!!!");
	            }
	        }
	
	        return returnVal;
	    }
		
		var val= val();//初始化方法
	    console.log(val.getter("varity"));//  1
	    val.setter("va222rity",3);//不存在重新添加並賦值
	    console.log(val.getter("va222rity"));  // 3
//		閉包的一個實際的應用   不會發生誤操作(讀寫已經分離)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章