本文同步分享於個人部落格:Liwen Chiou | Digital Architect & Full-Stack Engineer
孩子,在踏上今日的領地前,先坐下來喝杯酒吧。
修煉的路很長,別急著奔跑,先聽聽這份卷軸裡的古老叮嚀。我在每一站的盡頭都為你鋪設了 「
實戰演武場 CodePen」。那不只是程式碼的拼湊,而是你在這場暴風雨中,試圖用邏輯點燃的一顆星火。
成功突圍後,別忘了帶著你的戰利品回到 「QuestBoard 佈告欄」。在那裡,你會發現自己從不孤單,公會的夥伴們都正舉杯等待你的歸來。記住...
「 導師看重的從來不是你的劍法有多華麗,而是當你被邏輯擊潰、滿身泥濘後,依然選擇握緊理性的劍柄,再次向真相發起衝鋒的勇氣。 」
「導師,為什麼我辛苦幫梅大叔設定好的『黑夜模式』介面,只要他一重新整理網頁,整個公會大廳就又變回白茫茫一片,差點閃瞎他的眼啊!」
我拍掉手上的公文塵埃,指著櫃檯後面的一個皮革小帳本說:「冒險者,那是因為你的程式碼只存在於當前的『執行泡泡(記憶體)』中。一旦泡泡破了(頁面重整),一切都會歸零。
今天,我要教你如何動用瀏覽器的 『自動存檔點 (Save Point)』。我們會把使用者的心聲,一字一句刻在瀏覽器的皮革帳本上。即便勇者關掉電腦去睡覺,明天醒來,他的偏好依然會在。這就是 LocalStorage 的持久化魔法。」
在瀏覽器的世界,我們有三種方式可以存檔,但它們的「保存期限」完全不同:
| 特性 | LocalStorage | SessionStorage | Cookie |
|---|---|---|---|
| 保存期限 | 永久存檔 (手動清才消失) | 關掉分頁即消失 | 設定時間到期消失 |
| 容量大小 | 約 5MB (最大) | 約 5MB | 極小 (4KB) |
| 主要用途 | 個人設定、待辦清單 | 臨時輸入、一次性狀態 | 廣告追蹤、身分驗證 |
🏹 導師的辨析: 在現代前端開發中,除非你要處理跟伺服器通訊的密碼金鑰(Cookie),否則 90% 的本機存檔,我們都優先指派 LocalStorage 出動。
LocalStorage 的操作非常直觀,就像在用一把四段式機關鑰匙:
// 1. 存入 (setItem):鍵, 值
localStorage.setItem("heroName", "辛爾梅");
// 2. 讀取 (getItem):直接拿鑰匙去取回數值
const myHero = localStorage.getItem("heroName"); // "辛爾梅"
// 3. 刪除 (removeItem):單項排除
localStorage.removeItem("heroName");
// 4. 清空 (clear):整個帳本燒掉重來
localStorage.clear();
導師的圖解心法: 想像 LocalStorage 是一個巨大的壁掛櫃,每個櫃子都有一個專屬標籤(Key)。你存進去的是文字(Value),拿出來的也是文字。
這是新手最容易踩到的陷阱:LocalStorage 只能存「字串」!如果你直接把一個物件存進去,它會變成無效的 [object Object]。
為了解決這個問題,我們需要「打包拆箱術」:
JSON.stringify() (打包):將物件幻化成字串,才能塞進櫃子。JSON.parse() (拆箱):將字串召喚回物件,才能用點符號 (.) 取值。const heroData = { name: "辛爾梅", level: 99 };
// ❌ 錯誤做法:直接存
localStorage.setItem("save", heroData); // 毀了,裡面會變 "[object Object]"
// ✅ 正確做法:先打包再存
localStorage.setItem("save", JSON.stringify(heroData));
// 從櫃子拿出來時,記得拆箱
const getSave = JSON.parse(localStorage.getItem("save"));
console.log(getSave.name); // "辛爾梅"

btn.addEventListener("click", () => {
document.body.classList.toggle("dark-mode");
// 然後呢?沒有存檔,重整頁面後使用者又要點一次
});
// 1. 初始化:頁面啟動時先讀取帳本
const currentTheme = localStorage.getItem("theme");
if (currentTheme === "dark") {
document.body.classList.add("dark-mode");
}
// 2. 切換時:同步寫入帳本
btn.addEventListener("click", () => {
const isDark = document.body.classList.toggle("dark-mode");
localStorage.setItem("theme", isDark ? "dark" : "light");
});
導師講評: 學長的關鍵在於「雙向同步」:操作時存檔,讀取時應用。這就是專業應用程式的標配思維。
雖然 LocalStorage 很好用,但它有一個致命傷:任何這台電腦的腳本都能讀取它(XSS 攻擊風險)。
因此,專業職人的守則第一條:絕對不要在 LocalStorage 存下密碼、信用卡號或涉及資安的 Token。帳本是用來存「喜好設定」的,不是用來裝「金庫鑰匙」的。
另外,LocalStorage 的 5MB 限制雖然看起來很大,但如果你存入過多高解析度圖片的 Base64 編碼,帳本很快就會爆掉。優雅的開發者會懂得斷捨離。
孩子,導師當年第一次寫
JSON.parse時,因為沒考慮到「如果帳本裡根本沒這筆資料」的情況,導致程式直接崩潰。記住,當
localStorage.getItem()找不到鑰匙時,它會傳回null。如果你對null進行JSON.parse沒問題,但如果你後續直接拿它來點屬性(例如data.name),就會引發大災難。養成習慣:在操作存取回來的資料前,先用 Day 12 教過的邏輯判斷檢查它是否存在。
天色微亮,營火雖已燃盡,但你眼中卻閃爍著領悟的光芒。在前往演武場挑戰關卡前,我已經幫你把靈魂碎片精煉成了這份「戰術錦囊」。拿好它,今日的任務不再是負擔,而是你證明自我的舞台。去吧,公會的英雄榜在等著你的戰報。
JSON.stringify 直接把一個陣列存入 LocalStorage,拿出來時它會變什麼樣子?還能用 forEach 嗎?