徹底理解js中的閉包

2022-02-23 23:59:00 字數 2021 閱讀 6081

閉包是js的乙個難點也是它的乙個特色,是我們必須掌握的js高階特性,那麼什麼是閉包呢?它又有什麼用呢?

我們都知道,js的作用域分兩種,全域性和區域性,基於我們所熟悉的作用域鏈相關知識,我們知道在js作用域環境中訪問變數的權利是由內向外的,內部作用域可以獲得當前作用域下的變數並且可以獲得當前包含當前作用域的外層作用域下的變數,反之則不能,也就是說在外層作用域下無法獲取內層作用域下的變數,同樣在不同的函式作用域中也是不能相互訪問彼此變數的,那麼我們想在乙個函式內部也有限權訪問另乙個函式內部的變數該怎麼辦呢?閉包就是用來解決這一需求的,閉包的本質就是在乙個函式內部建立另乙個函式。

我們首先知道閉包有3個特性:

①函式巢狀函式

②函式內部可以引用函式外部的引數和變數

③引數和變數不會被垃圾**機制**

本文我們以閉包兩種的主要形式來學習

①函式作為返回值

在這段**中,a()中的返回值是乙個匿名函式,這個函式在a()作用域內部,所以它可以獲取a()作用域下變數name的值,將這個值作為返回值賦給全域性作用域下的變數b,實現了在全域性變數下獲取到區域性變數中的變數的值

再來看乙個閉包的經典例子

一般情況下,在函式fn執行完後,就應該連同它裡面的變數一同被銷毀,但是在這個例子中,匿名函式作為fn的返回值被賦值給了fn1,這時候相當於fn1=function(),並且匿名函式內部引用著fn裡的變數num,所以變數num無法被銷毀,而變數n是每次被呼叫時新建立的,所以每次fn1執行完後它就把屬於自己的變數連同自己一起銷毀,於是乎最後就剩下孤零零的num,於是這裡就產生了記憶體消耗的問題

再來看乙個經典例子-定時器與閉包

寫乙個for迴圈,讓它按順序列印出當前迴圈次數

按照預期它應該依次輸出1 2 3 4 5,而結果它輸出了五次5,這是為什麼呢?原來由於js是單執行緒的,所以在執行for迴圈的時候定時器settimeout被安排到任務佇列中排隊等待執行,而在等待過程中for迴圈就已經在執行,等到settimeout可以執行的時候,for迴圈已經結束,i的值也已經程式設計5,所以列印出來五個5,那麼我們為了實現預期結果應該怎麼改這段**呢?(ps:如果把for迴圈裡面的var變成let,也能實現預期結果)

引入閉包來儲存變數i,將settimeout放入立即執行函式中,將for迴圈中的迴圈值i作為引數傳遞,100毫秒後同時列印出1 2 3 4 5

那如果我們想實現每隔100毫秒分別依次輸出數字,又該怎麼改呢?

在這段**中,相當於同時啟動3個定時器,i*100是為4個定時器分別設定了不同的時間,同時啟動,但是執行時間不同,每個定時器間隔都是100毫秒,實現了每隔100毫秒就執行一次列印的效果。

②閉包作為引數傳遞

在這段**中,函式fn1作為引數傳入立即執行函式中,在執行到fn2(30)的時候,30作為引數傳入fn1中,這時候if(x>num)中的num取的並不是立即執行函式中的num,而是取建立函式的作用域中的num這裡函式建立的作用域是全域性作用域下,所以num取的是全域性作用域中的值15,即30>15,列印30

最後總結一下閉包的好處與壞處

好處①保護函式內的變數安全 ,實現封裝,防止變數流入其他環境發生命名衝突

②在記憶體中維持乙個變數,可以做快取(但使用多了同時也是一項缺點,消耗記憶體)

③匿名自執行函式可以減少記憶體消耗

壞處①其中一點上面已經有體現了,就是被引用的私有變數不能被銷毀,增大了記憶體消耗,造成記憶體洩漏,解決方法是可以在使用完變數後手動為它賦值為null;

徹底弄懂JS中閉包

閉包概念 閉包就是有權訪問另乙個函式作用域中變數的函式.分析這句話 1.閉包是定義在函式中的函式.2.閉包能訪問包含函式的變數.3.即使包含函式執行完了,被閉包引用的變數也得不到釋放.例子分析 1 function add return arr var temp add temp 0 大家猜猜這個結...

JS中閉包的理解

閉包其實就是乙個函式,什麼樣的函式?能夠訪問另乙個函式作用域中變數的函式。在回答這個問題之前,我先提乙個假設,我們都知道在內部的函式可以訪問外部函式的變數,假設現在就是有這麼乙個需要,需要外部環境來訪問函式的內部變數,怎麼辦?這時就要用到閉包,這就要牽扯到閉包的實現原理,即作用域鏈的工作。每當函式建...

JS中的閉包理解

一 變數的作用域 變數的作用域兩種 全域性變數和區域性變數。函式內部可以直接讀取全域性變數。在函式外部自然無法讀取函式內的區域性變數。函式內部宣告變數的時候,一定要使用var命令。如果不用的話,實際上宣告了乙個全域性變數 二 如何從外部讀取區域性變數?那就是在函式的內部,再定義乙個函式。functi...