以下是一個閉包
從開始學 JS 起,我其實覺得閉包(Closure)是一個很奇怪的知識,翻閱各種網路文章,我大概知道了
…但又怎麼樣呢?這感覺就是一個JS冷知識。雖然為了面試記住很多閉包的知識,但我卻始終搞不懂「為什麼需要閉包?」
因此這篇文章,我不想深究閉包的細節,主要更想探討的是「為什麼會需要閉包?它的用處或應用情境是什麼?」
假設你想要寫一個按鈕<Button>
,你會怎麼做呢?
首先,你定義了此開關按鈕有「打開/關閉」兩種狀態,那程式碼可能如下:
因此,當按鈕被點擊時
假設現在不止一個按鈕,而是想要兩個按鈕,那要怎麼辦呢? 總不能大家都共用「status」一個變數吧?因為這樣會互相干擾,因此可能的寫法就變成如下:
沒錯,我們幫每一個 status 和 clickButton 都加上編號,這樣就不會互相干擾了!
OK,這樣不錯,但假設有100個按鈕呢?
突然的,上面這種寫法就會變得冗余
從上面的方式我們可以看到這樣的寫法,其實有點冗余
這樣各自命名麻煩,不如直接寫成物件,這樣大家都可以有自己的狀態。
這樣不錯,大家都可以叫做status跟clickButton了,彼此互不干涉!
用物件的方式很不錯,但是會有一個問題——就是有人可以不按照規定用clickButton()
,就自己去更改按鈕的狀態。比如說
有時候確實不一定會怎樣,然而,很多時候在設計資料結構時,我們會期望大家還是可以照著規範來操作狀態,因為直接操作狀態可能會有許多問題。
比如說,我們就不會希望有人把 status 亂塞值,例如:
或是
我們希望,使用者一率使用 ButtonA.clickButton()
來去更改狀態,我們其實都期待——狀態最好在用規範好的方式被操作
你可能會想,真的會有開發者在 ButtonA.status
亂塞東西嗎?如果這個程式是你寫的,你當然不會這樣做。
但如果是多人合作狀態,或是你是一個套件的開發者。你無法預測他人會如何使用你提供的資料結構,因此這時候就會希望,別人可以遵守制定好的方法去修改狀態,而不是可以直接取得狀態。
如果想為了避免使用者直接去更改狀態,並只能透過規定好的方法去更改狀態,這時候就可以使用到閉包
這時候,閉包「內層的變數不會被釋放,可以被重複使用,但又不會被外面讀取」的特性就會發會作用,因此,在這個寫法中
因此,你不能用操作物件的方式直接更改
就必須用規定的函式更改
這時候,我們就有一個健康的按鈕系統了!
閉包的用處在於「狀態管理」以及「強制別人要依據規範(函式)操作狀態,而不能擅自更改」
但理解閉包的好處後,開發者可能仍然會想「但我實際上好像沒有這樣寫過耶?」
確實,開發上我們不一定會碰到 —— 但如果你是一個前端框架的使用者,我猜你可能會在不經意的時候就使用別人的閉包。
一個閉包例子,可能就是Redux。Redux 本身是 React 的一個狀態管理的系統,簡單來說,開發者可以透過 createStore 來創建一個狀態,以及定義使用者應該遵守什麼方式(函式)才能修改狀態。(就跟我們上面做的事情一樣)
而如果閱讀createStore的原始碼,我們就會發現它就是一個閉包
閉包的用處在於,「狀態管理」以及「強制它人依據規範操作狀態,而不能直接更改狀態」,因此假設你有類似的需求,閉包是個好工具。
開發者不一定會是常的寫到閉包,我們平常可能比較是閉包的使用者(例如:Redux)。但如果你想成為一個可以幫別人寫一些有用函式庫的開發者,你就會需要知道如何寫閉包了,因為你會希望你的使用者用你可以預期的方式使用你的資料結構。
Quick Links
Legal Stuff
Social Media