JavaScript 學習筆記 - LocalStorage


前言

本文主要介紹本地存儲的基本使用,以及它和 Cookie、SessionStorage 的區別。

在 HTML5 之前,本地存儲數據一般是通過 Cookie 來完成的。我們可以把 Cookie 理解為一個長度有限的字符串,服務端和客戶端都能讀寫這個字符串,並且每次請求時,都會把 Cookie 發送到服務端。

通常,我們可以利用這個字符串來保存用戶名、密碼等數據,來實現記住密碼、自動登錄等功能。

但是,Cookie 本來就不是用來存儲數據的,所以會有一些局限性:

  • 存儲空間有限,最多也就是幾十 K 的大小。
  • 每次請求都發送到服務器,浪費寬帶。
  • 使用起來比較麻煩的,需要自己封裝操作函數。

本地存儲的簡單使用

本地存儲(LocalStorage)是一種基於鍵值對的持久化存儲方案。“持久化存儲”就意味着,如果不手動清除,數據就永遠不會過期。

基於鍵值對的存儲方案,使用起來是很方便的。我們可以通過 localStorage.setItem(key, value) 來保存數據。

比如保存一個用戶名:

javascript-demo/localstorage.html

localStorage.setItem('name', 'hello')

然后就可以通過 localStorage.getItem(key) 的方式來獲取數據:

localStorage.getItem('name') // hello

LocalStorage 還支持直接對 localStorage 對象的屬性進行操作來存取數據,效果和 setItemgetItem 是一樣的。

localStorage.hi = 'Hi'
console.log(localStorage.hi) // Hi

以上代碼等同於:

localStorage.setItem('hi', 'Hi')
console.log(localStorage.getItem('hi')) // Hi

存儲對象

本地存儲只支持字符串存儲,存儲任何類型的數據,都會被轉換成字符串。

javascript-demo/localstorage-number.html

localStorage.setItem('age', 1024)
console.log(typeof localStorage.getItem('age')) // string

讀取完數據后,還要把數據轉成 Number 類型,很麻煩。有時候,我們還需要存儲復雜的數據結構。不可能像下面那樣將對象的屬性一個個存儲,再一個個讀取。

javascript-demo/localstorage-object.html

// 保存對象
let obj = {
    name: 'hello',
    age: 1024
}
localStorage.setItem('name', obj.name)
localStorage.setItem('age', obj.age)
// 讀取對象
let newObj = {
    name: localStorage.getItem('name'),
    age: parseInt(localStorage.getItem('age'))
}
console.log(newObj)

這時,我們需要利用 JSON API,來簡單封裝本地存儲。原理是保存數據前,通過 JSON.stringify 把數據轉換成 JSON 字符串再保存;讀取數據后,通過 JSON.parse 把 JSON 字符串轉換成原來的值。

// 簡單封裝
const storage = {
    set: function (key, value) {
        localStorage.setItem(key, JSON.stringify(value))
    },
    get: function (key) {
        return JSON.parse(localStorage.getItem(key))
    }
}
// 保存對象
let obj = {
    name: 'hello',
    age: 1024
}
storage.set('obj', obj)
// 讀取對象
console.log(storage.get('obj'))

這很方便,存取數字類型時也不需要轉換了。

storage.set('age', 1024)
console.log(typeof storage.get('age')) // number

API 介紹

一般來說,setItemgetItem 就足夠用了。這里大致介紹一下常用的屬性和方法,有興趣的了解一下。

  • localStorage.length:獲得存儲的鍵值對的的個數。
  • localStorage.key(n):獲得存儲的第 n 個元素對的鍵值(也叫做鍵名,不要和值搞混了)(下標從 0 開始)。
  • localStorage.getItem(key):獲取 key 對應的 value。
  • localStorage.key:獲取 key 對應的 value,相當於 getItem。也可以直接賦值,則相當於 setItem
  • localStorage.setItem(key, value):添加鍵值對到存儲。
  • localStorage.removeItem(key):移除鍵值為 key 的鍵值對。
  • localStorage.clear():清除所有數據。

在數據存儲方面,Cookie 的不足,也就是本地存儲的優勢,相對於 Cookie,本地存儲的優勢在於:

  • 較大的存儲空間。雖然 W3C 對存儲空間沒有限制,但瀏覽器有。不同的瀏覽器的限制大小可能不同。IE8 上是 10MB,Chrome 是 5MB(數據源於網絡,本人未去證實)。在未來可能會更大。
  • 不用每次請求都發送到服務器,提高請求速度。
  • 足夠好用的 API 支持,操作簡單。

盡管本地存儲功能強大,但它和 Cookie 的分工不同,還無法用來取代 Cookie。

一般來說,Cookie 用來與服務器進行交互,而不是用來存儲。而 LocalStorage 僅用來存儲。

同源限制

LocalStorage 同樣受限於同源策略。不同源之間的數據無法共享。關於同源策略,不懂的可以看我的這篇文章:前端學習筆記 - 跨域

Session Storage

SessionStorage 和 LocalStorage 功能類似,區別僅僅是數據保存時間的不同而已。LocalStorage 是持久存儲的,如果不手動清除,數據就永遠不會失效。而 SessionStorage 的數據存儲在窗口對象中,一旦窗口對象沒了(用戶關閉瀏覽器或標簽頁),數據就會丟失。

我們可以簡單地測試一下:

javascript-demo/sessionstorage.html

console.log(sessionStorage.getItem('name'))
sessionStorage.setItem('name', 'hello')
console.log(sessionStorage.getItem('name'))

第一次運行時,控制台輸出:

null
hello

刷新一下瀏覽器,控制台輸出:

hello
hello

然后打開一個新標簽頁(不要關閉原來的標簽頁),在新標簽頁中打開示例,可以看到控制台輸出:

null
hello

可見,對於不同的標簽頁,SessionStorage 是無法共享數據的。一旦關閉了標簽頁或瀏覽器,存儲的數據就再也找不回了。

應用

  • 比如文章編輯器的實時保存(以及斷網時的保存策略)。
  • 一些不重要的用戶設置。比如某些閱讀類的網站,用戶可以設置文章的字體大小、配色等。這些數據有時沒必要保存在數據庫。
  • 比如。。。你仔細想想,還是有很多的。

需要注意的是,不要太依賴於本地存儲。本地存儲雖然是永久的,但隨時可能被用戶或瀏覽器清理掉。此外,不同瀏覽器間也是無法共享數據的。

總結

無聊的補充

我們可以這樣獲取已經占用的存儲空間大小:

var total = unescape(encodeURIComponent(JSON.stringify(localStorage))).length;
console.log(total / 1024 + 'K')

5M 左右的空間,也是會用滿的:

for (let i = 0; i < 1024 * 1024; i++) {
    localStorage.setItem('test' + i, 'hello')
}

控制台輸出:

Uncaught DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of 'test356613' exceeded the quota.

意思是超出配額了。

我們也可以來測試你的瀏覽器對本地存儲的最大允許容量。

for (let i = 0; i < 1024 * 1024; i++) {
    var total = unescape(encodeURIComponent(JSON.stringify(localStorage))).length;
    console.log(total / 1024 / 1024 + 'M')

    localStorage.setItem('test' + i, '0')
}

我試了兩個瀏覽器,360瀏覽器崩潰了,谷歌瀏覽器顯示 7M 多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM