主要分三部分說:
1、什麼是閉包?2、閉包有什麼好處?應用在哪裏?javascript
第一個特色:能夠是函數嵌套函數html
function fna(){ function fnb(){} }
第二個特色:內部函數能夠引用外部函數的參數和變量java
function fna(){ var b=5; function fnb(){ console.log(b); } fnb(); } fna();
b變量都要被內部函數fnb()引用到,會一直駐紮在內存中,不會被垃圾回收的,也就是說參數和變量不會被垃圾回收機制所收回。
那麼什麼是js垃圾回收機制呢?閉包
function fna(){ var a=1; } fna();
例如,上面寫了個普通函數fna(),當fna();執行完畢後變量a就不存在了,爲了節省內存。
例1:函數
function fna(){ var a=5; function fnb(){ console.log(a); } return fnb; } var fnc=fna(); fnc(); //5
變量c就是返回的fnb函數,fnc()執行的時候 變量a並無消失,一直駐紮在內存中的,這時會彈出5的.這就是簡單的閉包形式。code
好處:
1.但願一個變量長期駐紮在內存當中
2.避免全局變量的污染htm
var a=1; function fna(){ a++; console.log(a); } fna(); //2 fna(); //3 console.log(a);//3
a是個全局變量,一直駐紮在內存中,依次執行會累加。索引
function fna(){ var a=1; a++; console.log(a); } fna(); //2 fna(); //2
若是把變量a設置爲局部變量,每調用一次代碼從新執行,調用後a就不存在,下次調用的時候a仍是1;那麼怎麼能作到a便是局部變量,a又能累計呢?
這就是閉包所能作到的。
例2:ip
function fna(){ var a=1; return function () { a++; console.log(a); }; } var fnb=fna(); fnb(); //2 fnb(); //3 console.log(a) //undfined
構成了函數嵌套函數,當外面的函數執行完畢後,內部函數依舊能夠調用到變量a;內存
(function(){ console.log(1); })();
()放函數,函數聲明就會變成函數表達式,再加()當即執行。
至此能夠把例2中的代碼改寫一下.
var fna= (function () { var a=1; return function () { a++; console.log(a); } })(); fna();//2 fna();//3
var a=1在外面是調用不到,減小全局變量的污染,把內部函數變爲私有的,
這也就是
3.變量私有
var aaa = (function(){ var a = 1; function bbb(){ a++; console.log(a); } function ccc(){ a++; console.log(a); } return { b : bbb, c : ccc } })(); //aaa.b(); //2 //aaa.c(); //3
在循環中直接找到對應元素的索引
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> <li>11111111111</li> <li>11111111111</li> <li>11111111111</li> </ul> <script> window.onload = function(){ var aLi = document.getElementsByTagName('li'); for(var i=0;i<aLi.length;i++){ aLi[i].onclick = function(){ console.log(i);//3 }; }; }; </script> </body> </html>
console.log(i)彈出3,爲何呢?很明顯,當循環執行結束的時候
aLi[i].onclick = function(){ console.log(i);//3 };
還沒執行,當點擊的時候纔會執行,但此時i已經變成3了。能夠利用閉包改寫,能夠把循環中的i看成個參數傳進去,就以前所說的內部函數能夠引用外部函數的參數和變量。
for(var i=0;i<aLi.length;i++){ (function(i){ aLi[i].onclick = function(){ console.log(i); }; })(i);
把i當成參數穿進去。除了這種寫法還有另一種方式
for(var i=0;i<aLi.length;i++){ aLi[i].onclick = (function(i){ return function(){ console.log(i); } })(i);