切換語言為:簡體

全面深入對比Cookie、LocalStorage、SessionStorage三者差異性

  • 爱糖宝
  • 2024-10-16
  • 2038
  • 0
  • 0

三者基本使用

1. Cookie 的基本使用

設定 Cookie

function setCookie(name, value, days) {
    let expires = "";
    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toUTCString();
    }
    document.cookie = name + "=" + (value || "") + expires + "; path=/";
}

// 示例:設定 Cookie 有效期為 7 天
setCookie('username', 'bob', 7);

獲取 Cookie

function getCookie(name) {
    const nameStr = name + "=";
    const ca = document.cookie.split(';');
    for (let i = 0; i < ca.length; i++) {
        let c = ca[i];
        while (c.charAt(0) === ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameStr) === 0) return c.substring(nameStr.length, c.length);
    }
    return null;
}

// 示例:獲取 Cookie
const username = getCookie('username');
console.log(username); // 輸出:bob

刪除 Cookie

function delCookie(name) {
    document.cookie = name + '=; Max-Age=-99999999;'; // 立即過期
}

// 示例:刪除 Cookie
delCookie('username');

設定安全標誌

爲了提高安全性,可以設定 Secure 和 HttpOnly 標誌。

  • Secure:表示 Cookie 只能透過 HTTPS 協議傳輸。

  • HttpOnly:表示 Cookie 不能透過 JavaScript 訪問,只能透過 HTTP 請求訪問。

// 設定帶有 Secure 和 HttpOnly 標誌的 Cookie
document.cookie = "username=張三; Secure; HttpOnly; path=/";

5. 完整示例

2. localStorage 的基本使用

localStorage 是瀏覽器提供的一種儲存機制,允許網頁在使用者的本地計算機上儲存資料。這些資料即使在瀏覽器關閉後仍然存在,直到被使用者或網站主動清除。以下是 localStorage 的基本使用方法:

設定 localStorage

使用 setItem 方法將資料儲存到 localStorage 中。

// 儲存字串
localStorage.setItem('username', '張三');

// 儲存數字
localStorage.setItem('age', '25');

// 儲存物件(需要先轉換為 JSON 字串)
const user = { name: '李四', age: 30 };
localStorage.setItem('user', JSON.stringify(user));

// `localStorage` 儲存布林值時,需要注意布林值需要轉換成字串形式才能儲存,並且在讀取時需要將其還原成布林值
localStorage.setItem('isLoggedIn', 'true'); // 儲存 true 
localStorage.setItem('isFirstVisit', 'false'); // 儲存 false

獲取 localStorage

使用 getItem 方法從 localStorage 中獲取資料。

// 獲取字串
const username = localStorage.getItem('username');
console.log(username); // 輸出: 張三

// 獲取數字
const age = localStorage.getItem('age');
console.log(Number(age)); // 輸出: 25

// 獲取物件(需要先解析 JSON 字串)
const userString = localStorage.getItem('user');
const user = JSON.parse(userString || '{}');
console.log(user); // 輸出: { name: '李四', age: 30 }

// 獲取布林值 
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true'; // 轉換為布林值
console.log(isLoggedIn); // 輸出: true 
const isFirstVisit = localStorage.getItem('isFirstVisit') === 'false'; // 轉換為布林值 
console.log(isFirstVisit); // 輸出: false

刪除 localStorage

使用 removeItem 方法從 localStorage 中刪除特定的資料。

// 刪除單個數據
localStorage.removeItem('username');

// 刪除所有資料
localStorage.clear();

4. 檢查 localStorage 是否可用

在某些情況下,localStorage 可能不可用(例如,使用者禁用了本地儲存)。可以透過以下方式檢查 localStorage 是否可用:

function isLocalStorageAvailable() {
  try {
    const key = 'test';
    localStorage.setItem(key, key);
    localStorage.removeItem(key);
    return true;
  } catch (e) {
    return false;
  }
}

if (isLocalStorageAvailable()) {
  console.log('localStorage 可用');
} else {
  console.log('localStorage 不可用');
}

5. 監聽 storage 事件

當 localStorage 發生變化時,會觸發 storage 事件。可以在頁面中監聽這個事件來響應儲存的變化。

window.addEventListener('storage', (event) => {
  console.log('儲存發生變化:', event.key, event.newValue);
});

結論

  • setItem(key, value):儲存資料。

  • getItem(key):獲取資料。

  • removeItem(key):刪除特定資料。

  • clear():刪除所有資料。

  • storage 事件:監聽儲存變化。


3. sessionStorage 的基本使用

SessionStorage 是 Web Storage API 的一部分,用於在瀏覽器會話期間儲存資料。資料儲存在同一視窗或標籤頁內,關閉視窗或標籤頁後資料會被清除。

設定 sessionStorage

使用 setItem 方法將資料儲存到 sessionStorage 中。

// 儲存字串
sessionStorage.setItem('username', '張三');

// 儲存數字
sessionStorage.setItem('age', '25');

// 儲存物件(需要先轉換為 JSON 字串)
const user = { name: '李四', age: 30 };
sessionStorage.setItem('user', JSON.stringify(user));

// `sessionStorage` 儲存布林值時,同樣需要注意將布林值轉換為字串形式進行儲存,並在讀取時將其還原為布林值。
sessionStorage.setItem('isLoggedIn', 'true'); // 儲存 true 
sessionStorage.setItem('isFirstVisit', 'false'); // 儲存 false

獲取 sessionStorage

使用 getItem 方法從 sessionStorage 中獲取資料。

// 獲取字串
const username = sessionStorage.getItem('username');
console.log(username); // 輸出: 張三

// 獲取數字
const age = sessionStorage.getItem('age');
console.log(Number(age)); // 輸出: 25

// 獲取物件(需要先解析 JSON 字串)
const userString = sessionStorage.getItem('user');
const user = JSON.parse(userString || '{}');
console.log(user); // 輸出: { name: '李四', age: 30 }

// 獲取布林值 
const isLoggedIn = sessionStorage.getItem('isLoggedIn') === 'true'; // 轉換為布林值 
console.log(isLoggedIn); // 輸出: true 
const isFirstVisit = sessionStorage.getItem('isFirstVisit') === 'false'; // 轉換為布林值 
console.log(isFirstVisit); // 輸出: false

刪除 sessionStorage

使用 removeItem 方法從 sessionStorage 中刪除特定的資料。

// 刪除單個數據
sessionStorage.removeItem('username');

// 刪除所有資料
sessionStorage.clear();

4. 檢查 sessionStorage 是否可用

在某些情況下,sessionStorage 可能不可用(例如,使用者禁用了本地儲存)。可以透過以下方式檢查 sessionStorage 是否可用:

function isSessionStorageAvailable() {
  try {
    const key = 'test';
    sessionStorage.setItem(key, key);
    sessionStorage.removeItem(key);
    return true;
  } catch (e) {
    return false;
  }
}

if (isSessionStorageAvailable()) {
  console.log('sessionStorage 可用');
} else {
  console.log('sessionStorage 不可用');
}

5. 監聽 storage 事件

當 sessionStorage 發生變化時,會觸發 storage 事件。可以在頁面中監聽這個事件來響應儲存的變化。

window.addEventListener('storage', (event) => {
  console.log('儲存發生變化:', event.key, event.newValue);
});

結論

  • setItem(key, value):儲存資料。

  • getItem(key):獲取資料。

  • removeItem(key):刪除特定資料。

  • clear():刪除所有資料。

  • storage 事件:監聽儲存變化。

基礎封裝

Cookie 工具類 CookieUtils  是ts版本的 js把型別去除即可

export class CookieUtils {
  static setCookie(name: string, value: string, options?: {
    expires?: number | Date;
    path?: string;
    domain?: string;
    secure?: boolean;
    httpOnly?: boolean;
  }): void {
    let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;

    if (options?.expires) {
      const expires = typeof options.expires === 'number'
        ? new Date(Date.now() + options.expires * 24 * 60 * 60 * 1000)
        : options.expires;
      cookieString += `; expires=${expires.toUTCString()}`;
    }

    if (options?.path) {
      cookieString += `; path=${options.path}`;
    }

    if (options?.domain) {
      cookieString += `; domain=${options.domain}`;
    }

    if (options?.secure) {
      cookieString += '; Secure';
    }

    if (options?.httpOnly) {
      cookieString += '; HttpOnly';
    }

    document.cookie = cookieString;
  }

  static getCookie(name: string): string | null {
    const cookieArray = document.cookie.split('; ');
    for (let i = 0; i < cookieArray.length; i++) {
      const cookie = cookieArray[i].split('=');
      if (cookie[0].trim() === encodeURIComponent(name)) {
        return decodeURIComponent(cookie[1]);
      }
    }
    return null;
  }

  static deleteCookie(name: string): void {
    document.cookie = `${encodeURIComponent(name)}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
  }
}

// 使用示例

// 設定一個簡單的 Cookie
CookieUtils.setCookie('username', '張三');

// 設定帶有過期時間的 Cookie
CookieUtils.setCookie('username', '張三', { expires: 7, path: '/', domain: '.example.com', secure: true, httpOnly: true });

// 獲取 Cookie
const username = CookieUtils.getCookie('username');
console.log(username); // 輸出: 張三

// 刪除 Cookie
CookieUtils.deleteCookie('username');

'localStorage' | 'sessionStorage' 合併封裝 預設 localStorage

export class StorageUtils {
  private storageType: 'localStorage' | 'sessionStorage'

  constructor(storageType: 'localStorage' | 'sessionStorage' = 'localStorage') {
    this.storageType = storageType
  }

  private getStorage(): Storage {
    return this.storageType === 'localStorage' ? localStorage : sessionStorage
  }

  setItem(key: string, value: any): void {
    this.getStorage().setItem(key, JSON.stringify(value))
  }

  getItem(key: string): any {
    const value = this.getStorage().getItem(key)
    return value ? JSON.parse(value) : null
  }

  removeItem(key: string): void {
    this.getStorage().removeItem(key)
  }

  clear(): void {
    this.getStorage().clear()
  }
}

// 使用示例

// 使用預設的 LocalStorage
const localStorageUtils = new StorageUtils()

// 設定資料
localStorageUtils.setItem('user', { name: '張三', age: 30 })

// 獲取資料
const user = localStorageUtils.getItem('user')
console.log(user) // 輸出: { name: '張三', age: 30 }

// 刪除資料
localStorageUtils.removeItem('user')

// 清空所有資料
localStorageUtils.clear()

// 使用 SessionStorage
const sessionStorageUtils = new StorageUtils('sessionStorage')

// 設定資料
sessionStorageUtils.setItem('user', { name: '李四', age: 25 })

// 獲取資料
const sessionUser = sessionStorageUtils.getItem('user')
console.log(sessionUser) // 輸出: { name: '李四', age: 25 }

// 刪除資料
sessionStorageUtils.removeItem('user')

// 清空所有資料
sessionStorageUtils.clear()

注意:localStorage' | 'sessionStorage 一樣也可以過期時間封裝(但是好像一般不需要)還是給個參考吧

export class StorageExpiringUtils {
  private storage: Storage

  constructor(storageType: 'localStorage' | 'sessionStorage' = 'localStorage') {
    this.storage =
      storageType === 'localStorage' ? localStorage : sessionStorage
  }

  setExpiration(key: string, value: any, ttlInSeconds: number): void {
    const now = new Date().getTime()
    const item = {
      value,
      expiration: now + ttlInSeconds * 1000,
    }
    this.storage.setItem(key, JSON.stringify(item))
  }

  getExpiration(key: string): any {
    const itemStr = this.storage.getItem(key)
    if (!itemStr) {
      return null
    }

    const item = JSON.parse(itemStr)
    const now = new Date().getTime()

    if (item.expiration < now) {
      this.removeItem(key)
      return null
    }

    return item.value
  }

  removeItem(key: string): void {
    this.storage.removeItem(key)
  }

  clear(): void {
    this.storage.clear()
  }
}

// 使用示例

// 建立 StorageExpiringUtils 例項,預設使用 LocalStorage
const localStorageExpiringUtils = new StorageExpiringUtils()

// 設定帶過期時間的資料
localStorageExpiringUtils.setExpiration('token', 'abc123', 60 * 60) // 1小時後過期

// 獲取帶過期時間的資料
const token = localStorageExpiringUtils.getExpiration('token')
console.log(token) // 輸出: abc123

// 等待一段時間後再次獲取(假設已經過期)
setTimeout(() => {
  const expiredToken = localStorageExpiringUtils.getExpiration('token')
  console.log(expiredToken) // 輸出: null
}, 60 * 60 * 1000)

// 建立 StorageExpiringUtils 例項,使用 SessionStorage
const sessionStorageExpiringUtils = new StorageExpiringUtils('sessionStorage')

// 設定帶過期時間的資料
sessionStorageExpiringUtils.setExpiration('token', 'abc', 60 * 60) // 1小時後過期

// 獲取帶過期時間的資料
const sessionToken = sessionStorageExpiringUtils.getExpiration('token')
console.log(sessionToken) // 輸出: abc

// 等待一段時間後再次獲取(假設已經過期)
setTimeout(() => {
  const expiredSessionToken = sessionStorageExpiringUtils.getExpiration('token')
  console.log(expiredSessionToken) // 輸出: null
}, 60 * 60 * 1000)

三者對比

1. 儲存容量

  • Cookie:通常每個 Cookie 的大小限制在 4KB 左右,整個域名下的 Cookie 數量也有一些限制(通常最多 20 個)。

  • LocalStorage:儲存容量較大,通常限制在 5MB 到 10MB 不等,取決於瀏覽器。

  • SessionStorage:和 LocalStorage 類似,通常限制在 5MB 到 10MB,不同的是 SessionStorage 的資料會在會話結束後清除。

2. 資料永續性

  • Cookie:可以設定過期時間,預設情況下,瀏覽器關閉後,未設定過期時間的 Cookie 會被刪除。可以長期儲存資料。

  • LocalStorage:資料沒有過期時間,即使瀏覽器關閉,資料也會保留,直到顯式地刪除或清除。

  • SessionStorage:資料只在瀏覽器視窗或標籤頁開啟期間有效,關閉視窗或標籤頁後,資料會被清除。

3. 儲存方式

  • Cookie:每次請求都會被髮送到伺服器,支援跨域,但因為每次請求都攜帶,會增加頻寬開銷。

  • LocalStorage 和 SessionStorage:資料儲存在客戶端,不會隨每個請求傳輸,因此不會增加網路負擔。

4. 訪問方式

  • Cookie:可以透過 document.cookie 訪問,格式較為複雜,例如需要手動解析字串。

  • LocalStorage 和 SessionStorage:透過 localStorage 和 sessionStorage 物件進行訪問,簡單易用,支援 setItemgetItemremoveItem 和 clear 等方法。

5. 安全性

  • Cookie:可以設定 HttpOnly(防止 JavaScript 訪問)和 Secure(只在 HTTPS 環境下傳輸)標誌,增強安全性。

  • LocalStorage 和 SessionStorage:不支援這些安全標誌,資料更容易受到客戶端指令碼攻擊(如 XSS)。

6. 適用場景

  • Cookie:適合需要在伺服器與客戶端之間共享狀態的應用,例如使用者認證資訊、分散式追蹤等。

  • LocalStorage:適合儲存不需要頻繁交換的資料,例如使用者的偏好設定、快取資料等。

  • SessionStorage:適合一次性會話的資料儲存,例如表單填寫過程中的臨時資料。

小結

  • Cookie:適合持久且需要與伺服器通訊的資料,有嚴格的大小限制。

  • LocalStorage:適合長期儲存資料,大小限制較大,資料不會隨會話結束而消失。

  • SessionStorage:適合儲存會話相關的資料,資料在瀏覽器視窗關閉後被清除。

Cookie、LocalStorage 和 SessionStorage 的共享特性

1. 同域名下的共享

  • Cookie

    • 同域名下:Cookie 在同一域名下的所有頁面之間是可以共享的。只要設定了相同的 path 屬性,不同頁面都可以訪問同一個 Cookie。

    • 不同子域名:可以透過設定 domain 屬性來實現跨子域名的共享。例如,設定 domain=.example.com 可以使 a.example.com 和 b.example.com 共享同一個 Cookie。

  • LocalStorage

    • 同域名下:LocalStorage 在同一域名下的所有頁面之間是可以共享的。不同頁面可以訪問同一個 LocalStorage。

    • 不同子域名:LocalStorage 不能跨子域名共享。a.example.com 和 b.example.com 會有各自的 LocalStorage。

  • SessionStorage

    • 同域名下:SessionStorage 在同一域名下的所有頁面之間是不共享的。每個頁面開啟的新標籤頁或新視窗都會有獨立的 SessionStorage。

    • 不同子域名:SessionStorage 也不能跨子域名共享。a.example.com 和 b.example.com 會有各自的 SessionStorage。

2. 不同域名下的共享

  • Cookie

    • 不同域名下:預設情況下,Cookie 不能跨域名共享。但是,可以透過設定 domain 屬性來實現一定程度的跨子域名共享。

    • 完全不同的頂級域名:完全不同的頂級域名(如 example.com 和 example.org)之間無法直接共享 Cookie。

  • LocalStorage

    • 不同域名下:LocalStorage 不能跨域名共享。example.com 和 example.org 會有各自的 LocalStorage。

  • SessionStorage

    • 不同域名下:SessionStorage 不能跨域名共享。example.com 和 example.org 會有各自的 SessionStorage。

3. 不同頁面標籤之間的共享

  • Cookie

    • 不同頁面標籤:在同一域名下的不同頁面標籤之間,Cookie 是共享的。只要設定了相同的 path 屬性,不同頁面標籤可以訪問同一個 Cookie。

  • LocalStorage

    • 不同頁面標籤:在同一域名下的不同頁面標籤之間,LocalStorage 是共享的。不同頁面標籤可以訪問同一個 LocalStorage。

  • SessionStorage

    • 不同頁面標籤:在同一域名下的不同頁面標籤之間,SessionStorage 是不共享的。每個頁面標籤開啟的新視窗或新標籤頁都會有獨立的 SessionStorage。

總結

  • Cookie

    • 同域名下:共享

    • 不同子域名:透過設定 domain 屬性可以共享

    • 不同頂級域名:不共享

    • 不同頁面標籤:共享

  • LocalStorage

    • 同域名下:共享

    • 不同子域名:不共享

    • 不同頂級域名:不共享

    • 不同頁面標籤:共享

  • SessionStorage

    • 同域名下:不共享

    • 不同子域名:不共享

    • 不同頂級域名:不共享

    • 不同頁面標籤:不共享

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.