對javascript閉包的理解

慕斯不想說話發表於2019-04-10

  在工作中在很多情況下都會用到閉包,但是當別人問起閉包到底是什麼時,總是覺得說不出個所以然來,所以這次準備把閉包這個知識點好好的梳理一遍,以加深對閉包的理解。而且很多時候我們也容易將匿名函式跟閉包弄混,所以在此區分一下。寫得不對的地方歡迎各位大神指出。

1、什麼是閉包?

含義: 有權訪問另一個函式作用域中的變數的函式。
建立方式: 在一個函式內建立另一個函式。
目的: 主要是為了設計私有的方法和變數。
優點: 可以避免全域性變數的汙染。
缺點: 1、閉包會常駐記憶體,會增大記憶體使用量,使用不當很容易造成記憶體洩露。2、閉包只能取得包含函式中任何變數的最後一個值。
特性:
 1.函式巢狀函式;
 2.函式內部可以引用外部的引數和變數;
 3.引數和變數不會被垃圾回收機制回收;  4.在執行環境中,閉包的作用域包含著它自己的作用域、包含函式的作用域和全域性作用域;  5.當函式返回了一個閉包時,這個函式中的作用域將會一直儲存到閉包不存在為止。 閉包例子1:

    function test(){
        var x=10;
        function foo(){
            x*=2;
            return x;
        }
        return foo;
    }
    //或者
    function test(){
        var x=10;
        return  function(){
            x*=2;
            return x;
        };
    }
    var y=test();
    for(var i=0;i<4;i++){
    	console.log(y());//20、40、80、160
    }
複製程式碼

  結果分析:上述程式碼是一個閉包。我們在test()函式後,返回了一個指向函式foo物件的指標——foo(函式是物件,函式名實際上是一個指向函式物件的指標)。所以此時變數y其實就是一個指向函式foo物件的指標。但我們呼叫y()也就是在呼叫foo(),在函式foo()內,變數x可以看成是相對foo()函式的全域性變數。所以每次呼叫foo()函式後,函式內的X物件的記憶體不會被銷燬,所以會出現每次呼叫y()的結果是前面的兩倍。

閉包例子2:

    function createFunctions() {
    	var result = new Array();
    	for(var i = 0; i < 10; i++) {
    		result[i] = function() {
    			return i;
    		};
    	}
    	return result;
    }
    var result=createFunctions();
    for(var i=0;i<result.length;i++){
    	console.log(result[i]());/10個10
    }
複製程式碼

  結果分析:result是一個儲存10個函式的陣列。根據閉包的特性可知,i可以看成是resulti函式的全域性變數。所以迴圈10次後,i變成了10(最後一次i++等於10,迴圈條件不成立,但i作為一個相對全域性變數,在result[i]中的值最後都是10)。

閉包例子3:

function handler(){
    var dom=document.getElementById("test");
    dom.onclick=functin(){
        process(dom.id);
    }
}
//推薦
function handler(){
    var dom=document.getElementById("test");
    var id=dom.id
    dom.onclick=functin(){
        process(id);
    }
    dom=null;
}
複製程式碼

分析:上面

2、什麼是匿名函式?

  顧名思義,匿名函式就是沒有名稱的函式,由編譯器指定名稱並分配空間,通常直接作為引數傳遞。

匿名函式的形式如下:

//形式1 函式表示式
var test=function(){
    return 20;
}
//形式2 立即執行函式
(function(i){
    rentun i
})(5);
形式2可以變成如下:
var =testfunction(i){
    return i;
}
test(5);
複製程式碼

  立即執行函式的模式是為了保護函式體中的資料不被外界訪問,以免被外界環境汙染,同時還不會在記憶體中留下對該函式的引用。

不同點: 匿名函式是指沒有指定函式名稱的函式,而閉包有權訪問另一個函式作用域中的變數的函式。有時候在閉包中使用匿名函式。
相同點: 他們都可以設計私有的方法和變數(如立即執行函式)、都可以避免全域性變數的汙染。

相關文章