整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
關於封裝 localStorage 的小技巧

前言
在開發網頁時,常常會需要使用到 window.localStorage 來儲存資料,但是 window.localStorage 本身的 API 並不是很好用,所以我們可以透過封裝的方式來讓它更好用。
window.localStorage
window.localStorage 是瀏覽器所提供的一個 Web API,只要你是網頁開發者你一定會使用過它,它可以讓我們在瀏覽器中儲存資料,並且不會因為關閉瀏覽器而消失,另一個則是 window.sessionStorage,它也是瀏覽器所提供的 Web API,但是它的特性是當瀏覽器關閉時就會消失,因此我們可以透過這兩個 Web API 來儲存資料。
但這一篇我將會著重於介紹 window.localStorage,因為它的特性是不會因為關閉瀏覽器而消失,因此我們可以透過它來儲存一些重要的資料,例如:使用者的登入資訊、使用者的偏好設定等等。
Note
window.sessionStorage的運作以及使用方式與window.localStorage一模一樣,只是它的特性是當瀏覽器關閉時就會消失,因此我們可以透過它來儲存一些不重要的資料,例如:使用者的暫存資料等等,但有趣的是window.localStorage是可以在不同網頁上共用資料,但window.sessionStorage則不行,畢竟它的特性就是當瀏覽器關閉時就會消失,因此window.sessionStorage只能在同一個網頁上共用資料。
那麼 window.localStorage 有以下幾種方法可以使用
window.localStorage.setItem(key, value):新增一筆資料window.localStorage.getItem(key):取得一筆資料window.localStorage.removeItem(key):刪除一筆資料window.localStorage.clear():刪除所有資料
當你使用 window.localStorage.setItem('myName', 'Ray') 之後,你可以在瀏覽器的開發者工具中的 Application 頁籤中的 Local Storage 中看到你新增的資料,如下圖

Note
各家瀏覽器呈現都差不多,由於我是使用 Firefox,因此可能會與你的瀏覽器呈現不同,但是大同小異,你可以自行嘗試。
window.localStorage 的缺點
那麼其實 window.localStorage 本身的 API 就是這麼簡單,但是它有幾個缺點,就是它的 API 其實有一些問題,什麼意思呢?
其實 window.localStorage 是可以儲存物件的,例如…
1 | |
但是如果你使用 window.localStorage.getItem('myObj') 來取得資料時,你會發現它會回傳 [object Object]。
難道這是 Bug 嗎?還是要用什麼特別的方法才能解析呢?其實原因是因為 window.localStorage 只能儲存字串,因此當你儲存物件時,你必須先將物件轉成字串,例如:
1 | |
這樣子你才可以正確的儲存物件。
當然不只有這個問題,剛剛有提到,因為 window.localStorage 只能儲存字串,因此當你取出資料時,你必須先將字串轉成物件,例如:
1 | |
那麼這就會延伸另一個問題,也就是如果 window.localStorage.getItem('myObj') 如果取出來是 null 的話,雖然 JSON.parse(null) 也會回傳 null,然後不會出現錯誤,但如果今天你的資料是 undefined 的話,那麼 JSON.parse(undefined) 就會出現錯誤
1 | |
又或者你在儲存資料時,忘記轉成字串,例如:
1 | |
雖然最簡單方式就是使用 try...catch 或者當出現 null 的時候就改回傳空物件,但是這樣子其實會讓程式碼變得很醜,因此我們可以透過封裝的方式來解決這個問題。
封裝 window.localStorage
首先封裝的方式有很多種,有些人會使用 Class 來封裝,有些人會使用 Function 來封裝,那麼這邊兩種方式我都會介紹,但是我個人比較喜歡使用 Function 來封裝,因此我會先介紹 Function 的方式,後面再介紹 Class 的方式。
那麼通常我們封裝後會放在 utils 資料夾中,因此我們可以在 utils 資料夾中新增一個 localStorage.js,接著我們就可以開始封裝了。
第一個要封裝的功能就是取得資料,因此我們可以新增一個 get 的方法,並且將 window.localStorage.getItem(key) 的功能封裝起來,例如:
1 | |
很簡單吧?但其實這樣是不夠的,如果開發者忘記傳入 key 的話,那麼就會出現 undefined,因此我們可以判斷一下 key 是否存在,如果不存在的話就回傳 console.error 警告給開發者,例如:
1 | |
這樣子使用者只要忘記傳入 key 的話,就會出現警告,這樣子就可以避免開發者忘記傳入 key

接著最後,我們取出來時,也要判斷一下,如果是 null 或者是 undefined 的話,就回傳空物件,例如:
1 | |
Note
要回傳空物件或者是空陣列,其實都可以,但是我個人比較喜歡回傳空物件,因為這樣子就可以直接使用Object.keys來判斷物件是否為空物件,例如:Object.keys({}).length === 0,但是如果是空陣列的話,就必須要使用Array.isArray來判斷,例如:Array.isArray([]) && [].length === 0。
接著使用時,就只需要引入 getStorageItem 這個 Function,並且傳入 key 就可以了,例如:
1 | |
發現了嗎?透過封裝之後,我們就不需要再使用 JSON.parse 來解析資料了,而且我們還做了一些判斷,讓開發者不會忘記傳入 key,這樣子就可以避免一些低級錯誤。
接著當然就是最常使用的 set 方法,也就是新增資料,封裝方式也是一樣概念,所以我就直接貼上來,例如:
1 | |
很簡單吧?其實封裝並不困難,但是透過這些封裝可以大幅度減少一些低級錯誤,例如:忘記傳入 key 或者是 value,甚至是忘記轉成字串,這些都可以透過封裝來避免,透過封裝也可以讓我們的程式碼更加的乾淨。
當然這邊其實還有一件事情是封裝的優勢,也就是當我們封裝引入後,我們可以判斷 window.localStorage 是否存在,如果不存在的話,我們就要提示開發者,當前的開發環境不支援 window.localStorage,例如:
1 | |
那麼問題來了,感覺我們封裝的功能越來越多了,那麼我們要怎麼管理呢?其實這時候就可以使用 Class 來封裝,例如:
1 | |
接下來使用時,就可以直接引入 LocalStorage 這個 Class,並且使用 LocalStorage.get('myObj') 來取得資料,或者是使用 LocalStorage.set('myObj', { name: 'Ray', age: 18 }) 來新增資料,例如…
1 | |
當我們使用 import LocalStorage from './utils/localStorage' 引入時,其實就已經執行了 new LocalStorage(),因此我們初始化時,就同時判斷了 window.localStorage 是否存在,如果不存在的話,就會出現警告,這樣子就可以避免開發者在使用時,忘記判斷 window.localStorage 是否存在的問題。
那麼我相信你對於 window.localStorage 的封裝應該有一些概念哩~
底下我也提供一個完整的範例,你可以參考看看~
1 | |
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ