坑爹的JS閉包,怎麼去理解才是正確的

2022-07-04 07:24:06 字數 2030 閱讀 7367

有好些天沒寫文章了,前面一直在搭建自己的部落格後台,由於網域名稱備案一直沒有下來,就只能繼續在這裡寫了。

今天寫些什麼了,一般大家比較關心,尤其學js的,就是又愛又恨的乙個概念——閉包。

說了這麼多,那麼閉包的定義到底是什麼了。大家一定要注意,不是說能夠訪問到其他作用域的變數就是閉包,這是很籠統的。準確來說,閉包是基於正常的垃圾**處理機制下的。也就是說,一般情況乙個函式(函式作用域)執行完畢,裡面宣告的變數會全部釋放,被垃圾**器**。但閉包利用乙個技巧,讓作用域裡面的變數,在函式執行完之後依舊儲存沒有被垃圾**處理掉。

可以文字你不太喜歡看,那好,我直接上**。這可能是很多解說閉包的案列,先拿來用再說。

function foo(x) 

}var bar = foo(2); // bar 現在是乙個閉包

bar(10);

我們來分析一下這一段**,在foo中,宣告乙個變數tmp,他屬於foo作用域下的變數。函式返回乙個函式,這個函式被巢狀,函式內部彈出x+y(++tmp)。這是個人都看得懂啊,那為什麼會出現閉包,怎麼出現的了。這接下來就是看執行的過程了,首先執行var bar = foo(2);那麼foo就執行了,引數2也傳進去了,但是執行完畢之後,tmp變數以及引數x就已經被釋放**了嗎?並沒有,因為返回值裡面還等待使用這些變數咯,所以此時,foo雖然執行了,但是foo的變數並沒有被釋放,在return在等待繼續使用這些變數了,這個時候bar就是乙個閉包。

然後我們再執行bar,結果是16,另外你再把bar裡面的引數改改,是不是結果又變化了勒?這就是閉包的神奇之處,它改變了js的記憶體機制有木有。

然後我們再看看長得很像閉包的形式

function foo(x) 

bar(10);

}foo(2)

如果按照某些教程說的,可以父級作用域訪問子級作用域的變數,foo在全域性中執行,執行過程中未必沒有訪問區域性變數?訪問到了吧,但他不是閉包。按照我之前說的思維再走一遍。

函式foo執行,執行完執行完畢之後沒我再執行的時候,是不是裡面的tmp,bar函式又重新宣告了。那麼根本就沒有阻止foo作用域中的變數被垃圾**吧,那怎麼又叫做閉包了?

再結合乙個閉包運用的最多的例子,就是for迴圈的問題,比如:

for(var i = 0;i<10;i++)

這看起來沒有任何問題啊,會輸出0,1,2,3,4,5,6,7,8,9

一般出問題出在**了,比如為很多個元素繫結乙個點選事件的時候

我們期望的是點選到某乙個按鈕就會輸出第幾個被點選到了語句,但是很遺憾,你永遠達不到你想要的效果,為什麼了。

因為你點選事件是在點選後才觸發的,而for迴圈當你執行隻後就已經全部執行完畢了執行完畢後 i 的值會是比len大 1 的,所以不管你怎麼點, i 的值在for執行完畢之後已經固定了,改變不了了。那有什麼辦法儲存這個 i 的值了。除了最基礎的給元素節點自定義屬性這個方法之外,就是我們所說的閉包了。那麼,怎麼用?

我現在的需求是要儲存住這個 i 的值,如果在當前作用域下是做不到的。而閉包的作用就是讓當前作用域的值不會被垃圾**,由於在es5中沒有塊級作用域的說法,所以得利用函式自己建立乙個作用域:

var btnlist = document.getelementsbyclassname("btn"),

len = btnlist.length;

for(var i = 0;i這又**產生了閉包了。別急,我們乙個個分析。for迴圈每一次都執行乙個 iief (自執行函式),每一次變數 i 被當做引數傳到iief中去 , 那麼這個自執行函式中建立了乙個變數,引數 j 然後元素節點 btnlist 繫結乙個onclick事件,執行函式裡面需要用到這個引數 j ,但是你又沒點 , 那麼這個遍歷 j 就沒有被清理 , 就一直在引數裡面被儲存著 , 每乙個iief都做一樣的事情 , 所以這個時候就產生了閉包 , 變數 j 並沒有被**,依然在等待你使用。

不知道你是否真正弄懂了哈,在看閉包之前先得把作用域給理解,否則你也是看不懂的。

實際上,在很多同學在平時練習過程中或多或少都用到過閉包,只不過因為概念不清晰所以你才不知道,現在翻翻你之前寫的**,如果真正懂了,那麼你會很輕易就找到你使用過的閉包了。

理解js的閉包

閉包 將內部函式儲存到外部時,將會生成閉包。閉包會導致原有的作用域鏈不釋放,造成記憶體洩漏。先來看乙個閉包的例子 functiona returnb vartemp a temp temp 此時輸出結果是2 和3,函式b和a形成了閉包,函式b被儲存到外部。functiontest functionb...

js 閉包的理解

閉包就是說,能夠讀取其他函式內部變數的函式。其實這句話我不是很明白,因為我覺得閉包的作用是 延遲函式執行 模擬私有變數 根據第二點的描述,應該是阻止其他東西訪問自身私有成員,到了這怎麼變成讀取其他函式內部變數了?反其道而行之?不管定義了,看看最經典的這個例子 延遲執行 function count ...

JS閉包的理解

一 什麼是閉包 閉包解釋 乙個擁有許多變數和繫結了這些變數的環境的表示式 閉包特點 函式巢狀函式 內部函式可以訪問外部函式的變數 引數和變數不會被 變數的作用域 要理解閉包,首先必須理解js特殊的變數作用域。變數的作用域無非就是兩種 全域性變數和區域性變數。閉包的幾大特性 本章講述的這些特性,並非是...