1. 程式人生 > >從編譯原理淺談閉包

從編譯原理淺談閉包

       剛學完編譯原理,再來看閉包這個東西,感覺理解真的深入不少。下面講一下閉包的一種實現方式,從三個部分解釋。

  第一部分:

     當新增一個變數時,計算機會在一塊記憶體空間內分配一個位置,並且記錄下這個變數的名稱與位置的對應關係。

           而這塊記憶體空間,我們暫且稱之為環境。

   第二部分:

在執行方法時,計算機會新開闢一塊記憶體空間,用來存放方法中的區域性變數。

      下面我們來看一個javascript的例子

var money=100;
   function Add(x){
      return x+money;
   }

     現在我們來看看計算機會幹些啥

     第一步:var money=100; 這條程式會讓計算機在當前環境中找個位置給money變數,這個環境我們就叫做環境1吧。

                接著是定義方法,同樣在環境1中找個位置給Add方法,這個位置儲存了方法的執行內容,還有定義時所在的環境,即環境1。

    

       第二步: 執行Add方法之前,先開闢一塊記憶體空間(叫做環境2)。

            因為有引數x,所以在環境2中為x找個位置。

            執行內容時,需要查詢變數時會先在當前環境(環境2)中找,若找不到就到外面一層環境(環境1)中找。

            因此,x在環境2中,而money在環境1中。

            最後執行結束,我們要考慮環境2會不會被銷燬,這個問題下面會繼續探討,當然在這個程式中,環境2會被銷燬。

      

 第三部分:

      熱身完了,我們來看閉包的實現

function A(){
      var count=0;
      
      function B(){
         count++;
         console.log(count);  //顯示count的值
      }
    }
   var c=A();
   c();
   c();

       

       首先,定義方法A,當前環境依然假設為環境1。      

       然後就要執行方法A。       

     

       執行方法時要開闢一塊記憶體空間,就叫做環境2吧。

      在環境2中定義了count變數,還有方法B。後將方法B返回,由環境1中的c接收。

      現在我們可以看到,c引用方法B,而方法B引用環境2,也就是說環境2依然被外界引用,所以即使方法A執行完了,環境2依然會被保留,count變數依然保留。

    

       之後呼叫方法B時,也就可以在環境2中訪問到count變數。

      現在可以猜測第一個c() 顯示1,第二個c() 顯示2

       確實也是這樣。

        簡單來說,閉包就是保留了一塊環境,並且可以通過方法訪問到這個環境。