1. 程式人生 > >工作一年,重新思考閉包

工作一年,重新思考閉包

功能

延長變數生存週期

圖片

一個經典的例子,這個時候我們就可以看到變數會隨著函式的退出而隨著作用域銷燬。如果我們想要長久的儲存這個變數怎麼辦,這個時候,我們就可以用到閉包了。

圖片

再舉一個例子,我們都知道 Object.prototype.toString.call(this) === '[object XXXX]' 用來判斷型別是一個非常好用的例子,如果我們需要判斷多個型別的話。當然不會像這麼來寫:

這裡寫圖片描述

因為這樣的話有著太多的重複程式碼了,而且我們可以發現程式碼中有太多相同的內容,這個時候我們就可以使用閉包來進行處理了。

這裡寫圖片描述

這樣就可以快速的生成方法了,當然,如果我們不用閉包來生成方法又會如何呢?

這裡寫圖片描述

可以看出,生成的方法並沒起來型別判斷的作用

用於封裝變數

大家都知道, js 相對於其它語言,沒有 private 私有這個概念。如果某些時候,我們希望使用私有變數的時候,這個我們可以使用閉包來封裝變數,來實現私有變數這個方法。

這裡寫圖片描述

我們也還可以用它來持久化儲存靜態變數

這裡寫圖片描述

因為函式是高階公民,我們還可以用於儲存函式。
這裡寫圖片描述

概念

我們通過了幾個簡單的小例子來演示閉包了,通過例子可以很輕鬆的理解剛開始學習 js 時看到阮一峰老師的部落格裡關於閉包的概念閉包就是能夠讀取其他函式內部變數的函式。 再回想我們的例子,是不是每次都是返回新的函式,函式裡運用了一些引數,但是這些引數並沒有在函式中宣告,而是在函式的上級作用域中聲明瞭,因為這些引數一直處於被引用狀態,所以垃圾回收機制並沒有銷燬它們,而是讓其常駐在記憶體中,所以我們就可以在其它的地方呼叫返回的函式,並繼續引用這些引數。

面向物件中的閉包

這裡寫圖片描述

還可以這麼寫
這裡寫圖片描述

在 ES6 中甚至是理所應當

這裡寫圖片描述

閉包與記憶體

關於閉包對於記憶體的影響,阮一峰老師曾經在部落格寫寫道 由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。 , 甚至還有一些聳人聽聞的說法如 閉包會造成記憶體洩漏,所以要儘量減少閉包的使用 。之所以這麼說的原因是,變數本應該隨著函式的退出而解除引用。但是因為我們使用閉包,我們主動的把一些本應該銷燬的變數常駐於記憶體中留待下次使用。如果僅僅是因為這個原因讓我們放棄使用閉包,這無異於端起碗吃飯,放下碗罵娘 。我們把這些變數放在閉包的作用域與放在全域性作用域上,對記憶體的影響是一致的,不過還因為使用閉包,避免了全域性變數名汙染。如果固執的以為這樣對記憶體有不好的影響,那麼可以手動的置為 null