關於js中函式的閉包 深入瞭解
閉包就是能夠讀取其他函式內部變數的函式。
即函式定義和函式表示式位於另一個函式的函式體內。而且,這些內部函式可以訪問它們所在的外部函式中宣告的所有區域性變數、引數和宣告的其他內部函式。當其中一個這樣的內部函式在包含它們的外部函式之外被呼叫時,就會形成閉包。也就是說,內部函式會在外部函式返回後被執行。而當這個內部函式執行時,它仍然必需訪問其外部函式的區域性變數、引數以及其他內部函式。這些區域性變數、引數和函式宣告(最初時)的值是外部函式返回時的值,但也會受到內部函式的影響。-----個人理解就是:閉包是能夠讀取其他函式內部變數的函式,即在外面可以呼叫函式中的函式的變數,其實他就是將函式內外部連線起來的橋樑
如下面例子4:
這段程式碼有以下兩個特點:
1、函式b巢狀在函式a內部;2、函式a返回函式b;
引用關係如下圖:
這樣在執行完var c = a()後,變數c實際上是指向了函式b,b中用到了變數i,再執行c()後就會彈出一個視窗顯示i的值(第一次為1)。這段程式碼其實就建立了一個閉包,為什麼?因為函式a外的變數c引用了函式a內的函式b,就是說:
當函式a的內部函式b被函式a外的一個變數引用的時候,就建立了一個我們通常所謂的“閉包”。
當函式b執行的時候亦會像以上步驟一樣。因此,執行時b的作用域鏈包含了3個物件:b的活動物件、a的活動物件和window物件,如下圖所示:
如圖所示,當在函式b中訪問一個變數的時候,搜尋順序是:
1. 先搜尋自身的活動物件,如果存在則返回,如果不存在將繼續搜尋函式a的活動物件,依次查詢,直到找到為止。
2. 如果函式b存在prototype原型物件,則在查詢完自身的活動物件後先查詢自身的原型物件,再繼續查詢。這就是Javascript中的變數查詢機制。
3. 如果整個作用域鏈上都無法找到,則返回undefined。
三、閉包的用途及優勢
(一)、用途
1、閉包可以讀取函式內部變數 2、將函式內部變數的值始終儲存在記憶體中
例子:
這個例子中的result實際上就是閉包函式b,他一共執行兩次,第一次值99,第二次值為100,這就說明i一直在記憶體中,而不是在第一次a函式呼叫之後就自動清除。另外還需注意iAdd=function(){i++;},這裡iAdd是全域性變數,且它的值為匿名函式,其實也是一個閉包。
(二)、優勢
1、保護函式內的變數安全。以最開始的例子為例,函式a中i只有函式b才能訪問,而無法通過其他途徑訪問到,因此保護了i的安全性。
2、在記憶體中維持一個變數。依然如前例,由於閉包,函式a中i的一直存在於記憶體中,因此每次執行c(),都會給i自加1。
3、通過保護變數的安全實現JS私有屬性和私有方法(不能被外部訪問)。
函式a的內部函式b被函式a外的一個變數引用的時候,就建立了一個閉包。