從編譯原理淺談閉包
剛學完編譯原理,再來看閉包這個東西,感覺理解真的深入不少。下面講一下閉包的一種實現方式,從三個部分解釋。
第一部分:
當新增一個變數時,計算機會在一塊記憶體空間內分配一個位置,並且記錄下這個變數的名稱與位置的對應關係。
而這塊記憶體空間,我們暫且稱之為環境。
第二部分:
在執行方法時,計算機會新開闢一塊記憶體空間,用來存放方法中的區域性變數。
下面我們來看一個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
確實也是這樣。
簡單來說,閉包就是保留了一塊環境,並且可以通過方法訪問到這個環境。