關於閉包的理解

由於之前在上學的時候,發現老師對着答案講題目特別的溜。因此寫文章以前,我去把查了一下閉包的概念,我將我對閉包的理解儘可能往官方解釋上面湊,結果湊到最後,依舊無法用通俗的語言去解釋這個概念。那麼我仍是講講我理念上的閉包吧 。面試

我理解的閉包:一個(存於內存的)封裝好的數據或方法。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

以上就是我我的對閉包的不太全面的理解,寫下來主要是爲本身之後作個記念,若是能幫助一些人則更爲開心,有理解不足的地方但願你們多多提意見。

相關文章
相關標籤/搜索