由於之前在上學的時候,發現老師對着答案講題目特別的溜。因此寫文章以前,我去把查了一下閉包的概念,我將我對閉包的理解儘可能往官方解釋上面湊,結果湊到最後,依舊無法用通俗的語言去解釋這個概念。那麼我仍是講講我理念上的閉包吧 。面試
我理解的閉包:一個(存於內存的)封裝好的數據或方法。ajax
先講封裝好的固定數據,舉個栗子:閉包
function testOne() { return 1 ; } var NumOne = testOne(); console.log(NumOne);//1
上面這個栗子就是我對閉包的一部分理解。
在說下面的話題以前,必須又得提到一個關於‘()’的理解。
個人理解上:
1 . ()的意思能夠理解成 '執行';函數賦值的時候是不用帶上()的,執行的時候才須要。異步
舉個栗子:函數
(function test(){console.log('hello Wolrd'})();//hello world
這實際上就等同於:this
function test(){console.log('hello Wolrd'}; test();//hello world
2 . ()中能夠帶入參數,參數能夠用於做爲閉包函數執行時候的某個常量,這個常量對於外部來講是個變量。這樣說可能有點繞,那麼說句廣告詞可能會好理解點:開局只有一把武器...那麼這武器,也就是()中的參數,它在遊戲開始以前是一個變量,你能夠選擇矛,錘...可是進入遊戲以後,這把武器就不能夠改了,當你執行操做的時候,選擇了矛的操做矛的屬性,選擇了錘的只能操做錘的屬性。線程
結合()的第二個特徵,再說一個封裝好的動態數據,代碼以下:code
var spear = {operation:'刺'}; var hammer = {operation:'揮'}; function con_opera(t) { return (t.operation); } console.log(con_opera(spear)); //刺 console.log(con_opera(hammer)); //揮
3.()的參數能夠爲多個,包括this,window,event等。對象
結合()的第三個特徵,再端盤關於封裝好的方法的栗子:遊戲
function plusFn(a,b){ console.log(a+b); } plusFn(3,4);//7
關於我對閉包的用途的理解 。
1.面向對象。
若是說如今如今有不少個玩家進遊戲選角色的時候要捏人,若是從過程上去處理,那無疑是不夠靈活的。
若是從對象上處理呢?
①.便於複用:
捏頭(頭部屬性);捏身子(身子屬性);捏手(手部屬性);捏腿(腿部屬性);
這樣的話,只要寫四個方法,就能夠拼接成一個捏人的方法。並且能夠重複使用這套方法,構成結構的多樣性。
②.便於代碼維護:
若是想要在身上捏對翅膀的話,徹底能夠再多加一個捏翅膀(翅膀屬性);
2.異步處理。
由於閉包使用的是參數,而不閉包使用的是變量,以前解釋過,參數爲函數內部的常量,這個值在調用閉包的時候已經設置好,不會隨着外界變量的改變而改變。
還有個是我的的習慣問題,我更喜歡的是寫好一個方法,而後處處使用,尤爲是ajax的時候,獲得參數的處理方法,success的時候 fun(返回值),error的時候 fun(默認值),並且因爲js的單線程多進程,頻繁切換進程但同一進程倒是按照順序執行,這樣的話,將方法閉包放入一個進程裏面能夠既方便又有效地避免異步引起的bug。
3.方便回調
從前有座山,山上有座廟,瞄裏有個老和尚,老和尚給小和尚講故事:。。。
這就是無限循環就是個回調函數。
(function test(){ console.log('從前有座山,山上有座廟,瞄裏有個老和尚,老和尚給小和尚講故事:'); test(); })();
閉包題的分析:
這裏從網上找了倆道比較經典的面試題,由於我實在也不知道它們初始出處是哪裏,原諒我無法寫引用地址。
1.
for(var i = 1; i <= 5; i++) { setTimeout( function () { console.log(i); }, 1000 ); } //5 5 5 5 5
改寫一下:
function test(t){ setTimeout( function () { console.log(t); }, 1000 ); } for(var i = 1; i <= 5; i++) { test(i); } //1,2,3,4,5
這個就是異步的問題,若是使用閉包,閉包被調用的時候,console.log()分配的參數則是1,2,3,4,5這五個常量。而不閉包,則是瞬間去給五個console.log()分配了變量i,而i在內存中是一個變量,在setTimeout設定的時間到達時,已是5了,這也是爲何一會兒輸出5個5的緣由。
2.
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3); var b = fun(0).fun(1).fun(2).fun(3); var c = fun(0).fun(1); c.fun(2); c.fun(3);
說實話,第一次作這題的時候,感受在坐升降機,又像在看無限放大的漩渦。
return的意思爲返回值,返回值的意思就一個函數的處理結果:加水(糖){return ‘糖水’}
a = fun(0);//fun(0,o),此時o爲undefined, 因此console.log 一個 undefined 並 return {fun:function(m)} 則 a = { fun:function(m){ return fun(m,0); } } a.fun(1) = function(1){ return fun(1,0); }; fun(1,0) = { console.log(0); return { fun:function(m) } };//因此會console.log一個0 a.fun(2)與a.fun(3)同a.fun(1); 關於b fun(0).fun(1) == a.fun(1)//到這層爲止,請參照a.fun(1)的解釋。因此會console.log undefined,0; fun(0).fun(1).fun(2)//這層 fun(0).fun(1) = { console.log(0); return{ fun:function(m){ return fun(m,1); } } }則fun(0).fun(1).fun(2) = fun(2,1); //運行到fun(0).fun(1).fun(2)這層 fun(2,1) = { console.log(1); return { fun:function(m) { return fun(m,2); } } }//因此會console.log一個1 則fun(0).fun(1).fun(2).fun(3) = fun(3,2);//同理於fun(2,1),因此會console.log一個2 //那麼c這邊就好解決的多了。 c = fun(0).fun(1) //相似於a.fun(1); 因此會console.log undefined,0; c.fun(2)與c.fun(3)//參考b 的fun(0).fun(1).fun(2) ,因此會console.log 1,1. //因此最後答案爲 undefined,0,0,0;undefined,0,1,2;undefined,0,1,1
以上就是我我的對閉包的不太全面的理解,寫下來主要是爲本身之後作個記念,若是能幫助一些人則更爲開心,有理解不足的地方但願你們多多提意見。