-
1 # 林妹妹影片
-
2 # 螞蟻他哥
閉包是指函式和其詞法環境的組合——
假設函式A包含了函式B,B裡面又包含了函式C,A(){B(){C(){}}}
假設每個函式都內部定義了自己的區域性變數,那麼函式C的詞法環境(它可以呼叫的變數範圍)是A和B以及C自己內部所有的變數環境;
函式B的話,它沒法呼叫子函式C的內部環境,可以用A和B自己本身的環境;A的話只能用自己內部詞法環境,連B的也拿不到。
這就是閉包的基本含義,再舉個例子來說明應用:
假設我現在想用for迴圈和console.log來輸出迴圈的值:
for(var i=0;i<5;i++){
console.log(i)
}
執行結果是輸出0,1,2,3,4;
現在我想1秒(1000毫秒)後輸出一次這個結果,即輸出時設定個時間間隔
即在for中新增setTimeout(funcname,1000);來實現每隔1000毫秒執行一次這個funcname函式,程式碼如下:
for(var i=0;i<5;i++){
setTimeout( function timer(){console,log(i);},1000);
}
執行結果試一下,結果卻是輸出了5個5,不是預期的01234;
回到ABC模型,for的環境看作A,環境中i值從0變到4;setTimeout看作函式B,console.log看作函式C,由於沒有定義區域性變數,BC和A的詞法環境都是一樣的;
當A中執行完迴圈時,i最終為5,並設定了5個setTimeout函式B,在1秒後,B函式執行內部的C函式來輸出i,由於C函式詞法環境和AB一樣,1秒後for迴圈已結束i值為4,執行完i++值為5,此時連續輸出5個5;
下面我們設定個閉包來把每種i值在取值後透過函式將其限定為區域性變數:
for(var i=0;i<5;i++){
(function(i){
setTimeout( function timer() {console,log(i);},1000);
})(i);
}
即在for中,透過(function(i){原函式內容})(i);的形式,將i值傳遞到該函式中成為該函式的詞法環境,設該函式為D,此時變成了:
A{D{設定i值{B{C{}}}}};
BCD的詞法環境都是A的基礎上外加傳入的i值,閉包也就發揮了它限定詞法環境的作用,程式碼也就可以按預期輸出了~
-
3 # 蘑菇頭MTV
在javascript中,閉包是一個難點,也是一個特色,很多高階應用都得靠它實現,而且也是不太容易完全理解的;閉包,顧名思義,就是封閉的,不對外開放的函式語句塊,你建立一個函式,實際上它就是一個閉包,不過,閉包通常是在函式內部,即函式中的函式,從而形成“鏈式作用域”。當然要理解閉包,我們得思考為什麼會有閉包這種概念,它的作用是什麼?下面通過幾個例子來說明下:
一、程式碼封裝在js中,函式外部全域性變數對函式內部是可見的,而在函式內部定義的變數,對外是不可見的。
利用這個特性,在開發中可以用閉包的形式封裝重要變數:
這樣封裝,變數age對外是不可見的,但是,在外部卻是可以操作變數age的。
二、快取在閉包中引用的變數,外層函式呼叫後,是不會被垃圾回收機制回收的,可用於快取計算的結果集,在下次使用時不用重新計算,對效能方面有一定提升;不過,這種情況是會造成記憶體洩漏的,所以,建議慎用閉包。
obj1在第三次呼叫的時候,其值為3,說明函式呼叫後,a的值一直快取在記憶體中。
三、自動執行(IIFE模式)用IIFE模式建立一個匿名函式,它會自動執行,在它內部的變數對外是不可見的。
在閉包內部把age的值改為30,data物件仍沒有改變,避免了汙染全域性變數。
經典面試題思考一、閉包中,this指向問題。
二、定時器與閉包
三、變數引用與閉包
看懂這三道面試題,對閉包的理解基本差不多了,另外,有不對的地方,還望高人指點。
-
4 # Fundebug
拿走不謝:
1. 透過示例學習JavaScript閉包:https://blog.fundebug.com/2017/08/07/javascript-closure-examples/
2. 我從來不理解 JavaScript 閉包,直到有人這樣向我解釋它..:https://blog.fundebug.com/2019/02/12/understand-javascript-closure/
3. 解密JavaScript閉包:https://blog.fundebug.com/2017/07/31/javascript-closure/
回覆列表
閉包就是能夠讀取其他函式內部變數的函式。例如在javascript中,只有函式內部的子函式才能讀取區域性變數,所以閉包可以理解成“定義在一個函式內部的函式“。在本質上,閉包是將函式內部和函式外部連線起來的橋樑。
簡單來說,形成閉包有兩個條件
1.函式中巢狀函式
2.內部函式引用了外部函式的引數