閉包一直是js中一個比較難於理解的東西,而平時用途又很是多,所以不得不對閉包進行必要的理解,如今來講說我對js閉包的理解。瀏覽器
要理解閉包,確定是要先了解js的一個重要特性, 回想一下,那就是函數做用域,做用域分全局和局部,因爲做用域鏈的存在,全局變量能在任何地方被訪問到,相反,局部變閉包
量只能在局部訪問,而沒法在全局的做用域中被訪問。由於若是你想訪問某個局部變量,首先搜索當前做用域中的變量,若是沒有,就會繼續向上搜索,直到做用域頂端。先看一個函數
例子:spa
1 var gl = 3; 2 var foo = function(){ 3 var lo=2; 4 } 5 foo(); 6 7 console.log(gl);//3 8 console.log(lo);//lo is not defined
那麼,要怎麼在外部做用域中拿到局部做用域的變量呢?換句話說,我怎麼在全局做用域中,拿到foo中的變量lo呢?code
例子:blog
1 function foo() { 2 var x = 2; 3 function bar() { 4 console.log(x); 5 }; 6 } 7 console.log(x);//x is not defined
我想在外部拿到x的值,該怎麼作?內存
首先,在外部做用域中是沒法訪問到foo函數甚至bar中的變量的,來看,在bar的做用域中,是能夠訪問foo的做用域中的變量的,所以,我只要在調用foo函數時,將他內部的作用域
bar函數返回出來,結果會怎樣呢?改寫一下以上代碼:io
1 function foo() { 2 var x = 2; 3 function bar() { 4 console.log(x); 5 }; 6 return bar 7 } 8 var func = foo(); 9 func(); //2
這樣就拿到了x的值,這就是最簡單的閉包。console
再來看一個比較常見的閉包應用場景:
1 function f1() { 2 var a = 1; 3 return function() { 4 a++; 5 console.log(a); 6 } 7 } 8 var f2 = f1(); 9 f2();//2 10 f2();//3 11 f2();//4
當我執行第一個f2的時候,a的值是從1變成了2,而在f1()調用時賦值給了f2,產生了一個引用,所以,a的值暫時被保存在閉包中或者是f2中,所以沒有被js的垃圾回收機制回收掉,因此,當我再一次調用f2的時候,a的值是上一次的值,也就是2,那麼這次調用a的值就變成3了,以此類推。
這些知識很基本的閉包基礎,其實只要是在寫js腳本,無時無刻都在不經意間會用到閉包,而閉包使用不當,會形成內存泄露,除非你強制關閉瀏覽器。