標籤:釋放 範圍鏈 count bsp javascrip 完成 簡單的 代碼 for
前文已經簡單的介紹了函數的閉包。函數的閉包就是有權訪問另一個函數範圍的函數,也就是函數內部又定義了一個函數。
1 var Super=function(num){2 var count=num;3 return function(){4 console.log(count);5 }6 }7 var result=Super(3);//此時result是一個函數8 result();//輸出3
上面的代碼定義了一個函數Super,同時在Super函數內部又定義了一個匿名函數作為傳回值。第七行調用Super函數,此時result是一個函數。第8行執行了result函數,輸出為3。這就是閉包的體現,因為上面的Super函數已經執行結束,但是它的內部變數count的值依然沒有被釋放,count的還在被匿名函數引用,所以沒有辦法釋放。如果要釋放count,我們需要 result=null ,將null賦值給result。
在前文已經介紹了函數的範圍鏈,當函數第一次被調用時會建立一個範圍鏈,並範圍鏈賦值給一個特殊的內部屬性。在範圍鏈中,函數的外部函數的使用中的物件位於第二位,外部函數的外部函數的使用中的物件位於第三位,以此類推,全域變數的範圍鏈位於最底部。
1 var count=2; 2 console.log(count);//2 3 count=3; 4 console.log(count);//3 5 var Super=function(num){ 6 var count=num;//範圍鏈第二位 7 console.log(count);//1 8 return function(){ 9 var count=5;//範圍鏈第一位10 console.log(count);11 }12 }13 var result= new Super(1);14 result();//輸出5
上面的代碼中,能夠清晰地瞭解到變數的範圍。閉包函數的內部變數位於最頂端,全域變數位於最底部。
在閉包中使用this對象也可能會導致一些問題,this對象是在函數運行時,基於函數的執行環境綁定的。在全域函數中,this指向window對象。而函數作為某個對象的方式調用時,this等於那個對象。不過匿名函數的執行環境具有全域性,因此this指向window
1 var obj={ 2 name:"heh", 3 getName:function(){ 4 var that=this; 5 return function(){ 6 return that.name; 7 } 8 } 9 };10 var one=obj.getName();11 var name=one();//heh
上面的代碼中,通過字面量的方式建立了對象obj,定義了對象的屬性name和方法getName。但是在getName內部,我們定義了閉包函數。如果想在閉包函數中訪問name,通過this是訪問不到的。所以需要在閉包函數的外部定義一個變數that,指向this。在getName中定義的變數,在閉包函數中仍然可以繼續使用。
JavaScript中沒有塊級範圍的概念,這意味著塊級中定義的變數,實際在函數內部都是可以使用的。
1 for(var i=0;i<10;i++){2 console.log(i);3 }4 console.log(i);//輸出10
上面的代碼中,我們在for迴圈中定義了變數i,但是我們在for迴圈外部依然可以使用i。for迴圈結束後,i變數並沒有被銷毀。
JavaScript可以使用匿名函數來模仿塊級範圍,從而避免該類問題的發生。
1 (function(){2 for(var i=0;i<10;i++){3 console.log(i);4 }5 })();6 console.log(i);
上面的代碼中,我們將塊級範圍放在了一個匿名函數中,同時將匿名函數放在一對括弧中,這表示一個函數運算式。在函數運算式外部的括弧,表示立即調用該函數。在第六行調用該函數的時候,會發生報錯,因為i並沒有定義。
1 var testFunc=function(){2 for(var i=0;i<10;i++){3 console.log(i);4 }5 };6 testFunc();7 console.log(i);
這個代碼,和我們上面的代碼是一樣的,都是通過函數運算式來定義函數。
1 function(){2 for(var i=0;i<10;i++){3 console.log(i);4 }5 }();
上面的代碼是錯誤的。我們知道函數的定義方法,可以通過function和函數運算式。通過function聲明函數的時候,function後面不能跟圓括弧。函數運算式的後面可以跟圓括弧。
1 var testFunc=function(){2 for(var i=0;i<10;i++){3 console.log(i);4 }5 }();
一般來說在開發過程中,應該盡量少向全域對象中添加函數和變數。太多的全域函數和變數容易導致命名的衝突以及記憶體的泄露。我們可以在塊級函數中完成所有的操作。
1 (function(){2 var now = new Date();3 console.log(now.getFullYear()+"-"+(now.getMonth()+1)+"-"+now.getDate()+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds());4 })();
通過上面的代碼,我們能夠當前的日期和時間。
淺談JavaScript的函數運算式(閉包)