⬆︎
×
CONF
TOC
CHAT
Hyplus目录
Hyplus设置
Customize your Hyplusite!

Web存储详解:localStorage、sessionStorage、cookie

JS前端开发3种常见的Web存储机制——localStoragesessionStoragecookie

1 localStorage(本地存储)

localStorage是HTML5引入的一种本地存储机制,使开发者能够在用户浏览器中持久存储数据。这些数据不会随着页面刷新而丢失,并且除非用户主动清除或删除它们,否则会一直保留在用户的设备上。

特点:

  • 数据没有过期时间。
  • 数据存储量通常较大(一般为5MB左右,具体大小取决于浏览器)。
  • 只能存储字符串类型的数据(复杂对象需先序列化)。
  • 同源策略限制:只有来自相同协议、域名和端口的页面可以访问同一localStorage数据。

1.1 基本操作

localStorage提供了一组简单方法来管理存储的数据(Key: Value)

  1. 存储数据:使用setItem()方法将数据存储至localStorage,注意所有数据都会被转换成字符串格式存储
localStorage.setItem('name', 'Akira Syma');
  1. 获取数据:使用getItem()方法从localStorage中检索数据
console.log(localStorage.getItem('name'));    // 输出:Akira Syma
  1. 删除数据:使用removeItem()方法删除特定键对应的值
localStorage.removeItem('name');
  1. 清空所有数据:使用clear()方法清空整个localStorage
localStorage.clear();
  1. 遍历所有键值对:使用key()方法结合循环可以遍历所有键值对
for (let i = 0; i < localStorage.length; i++) {
    let key = localStorage.key(i);
    console.log(`${key}: ${localStorage.getItem(key)}`);
}

1.2 序列化存储

由于localStorage只能存储字符串类型的数据,因此当需要存储复杂数据结构(如对象或数组)时,必须先将其序列化为JSON格式,再进行存储。

  • 存储对象:
const user = { name: 'Akira Syma', age: 108 };
localStorage.setItem('user', JSON.stringify(user));   // 序列化
  • 读取对象
const storedUser = JSON.parse(localStorage.getItem('user'));  // 反序列化
console.log(storedUser.name);   // 输出: Akira Syma

1.3 应用示例

localStorage非常适合用于存储不需要频繁更新且对安全性要求不高的数据,以下是一些典型的应用场景:

  • 用户偏好设置:如主题选择、语言偏好等
function saveTheme(theme) {
    localStorage.setItem('theme', theme);
}

function loadTheme() {
    return localStorage.getItem('theme') || 'light';    // 默认为浅色主题
}
  • 表单自动保存:在用户填写长表单时,可以定期保存表单状态,防止因意外关闭页面导致的信息丢失
setInterval(() => {
    const formState = document.querySelector('form').value;
    localStorage.setItem('formState', formState);
}, 5000);   // 每5秒保存一次
  • 离线应用:对于支持离线使用的应用,可以预先缓存一些关键数据,以便在网络不可用时也能提供基本服务

1.4 注意事项

使用localStorage时需注意以下几点:

  • 同源策略:localStorage数据仅在同一协议、域名和端口下可见,这有助于保护用户隐私,但也意味着不同网站之间无法共享数据。
  • 容量限制:这是各Web存储策略共同存在的问题,尽管大多数现代浏览器提供了较大的存储空间(约5MB),但当接近上限时,可能会触发警告或错误。合理规划存储内容非常重要。
  • 性能考虑:过度依赖localStorage可能会影响页面加载速度,尤其是在处理大量数据时。建议只存储必要的信息,并尽量减少读写频率。
  • 跨窗口同步问题:打开不同的URL标签,其localStorage是不同的。当多个标签页同时打开并尝试修改相同的localStorage数据时(多个标签页打开的是完全相同的URL),可能会出现数据不一致的情况。由此可通过监听storage事件来实现简单的跨窗口通信,如下所示——
window.addEventListener('storage', (event) => {
    if (event.key === 'sharedData') {
        console.log(`Shared data updated to: ${event.newValue}`);
    }
});

2 sessionStorage(会话存储)

sessionStorage是HTML5引入的一种本地存储机制,使开发者能够在用户浏览器中为当前会话(Session)存储数据。这些数据会在页面关闭时自动清除,并且不会随着页面刷新而丢失。

特点:

  • 数据仅在当前页面会话期间有效,关闭浏览器标签或窗口后数据会被清除。
  • 同一域名下的不同页面可共享sessionStorage中的数据(若是通过同一个浏览器标签打开的)。
  • 只能存储字符串类型的数据(复杂对象需先序列化)。
  • 同源策略限制:只有来自相同协议、域名和端口的页面可以访问同一sessionStorage数据。

2.1 基本操作

localStorage非常相似,sessionStorage提供了一组简单方法来管理存储的数据:

  1. 存储数据:使用setItem()方法将数据存储至sessionStorage,注意所有数据都会被转换成字符串格式存储
sessionStorage.setItem('name', 'Akira Syma');
  1. 获取数据:使用getItem()方法从sessionStorage中检索数据
console.log(sessionStorage.getItem('name'));  // 输出:Akira Syma
  1. 删除数据:使用removeItem()方法删除特定键对应的值
sessionStorage.removeItem('name');
  1. 清空所有数据:使用clear()方法清空整个sessionStorage
sessionStorage.clear();
  1. 遍历所有键值对:使用key()方法结合循环可以遍历所有的键值对
for (let i = 0; i < sessionStorage.length; i++) {
    let key = sessionStorage.key(i);
    console.log(`${key}: ${sessionStorage.getItem(key)}`);
}

2.2 序列化存储

localStorage相同,由于sessionStorage只能存储字符串类型的数据,因此当需要存储复杂数据结构(如对象或数组)时,必须先将其序列化为JSON格式,再进行存储。

  • 存储对象:
const user = { name: 'Akira Syma', age: 108 };
sessionStorage.setItem('user', JSON.stringify(user)); // 序列化
  • 读取对象
const storedUser = JSON.parse(sessionStorage.getItem('user'));    // 反序列化
console.log(storedUser.name);   // 输出: Akira Syma

2.3 应用示例

sessionStorage非常适合用于存储只需要在当前会话期间保持的数据,以下是一些典型的应用场景:

  • 表单自动保存:在用户填写长表单时,可以定期保存表单状态,防止因意外关闭页面导致的信息丢失(亦适合用localStorage实现)
setInterval(() => {
    const formState = document.querySelector('form').value;
    sessionStorage.setItem('formState', formState);
}, 5000);   // 每5秒保存一次

window.addEventListener('beforeunload', () => {
    if (sessionStorage.getItem('formState')) {
        alert('您的表单数据已自动保存。');
    }
});
  • 购物车信息:对于电子商务网站,可以在sessionStorage中暂时存储用户的购物车内容,直至其完成购买或主动清空购物车
function addToCart(item) {
    let cart = JSON.parse(sessionStorage.getItem('cart')) || [];
    cart.push(item);
    sessionStorage.setItem('cart', JSON.stringify(cart));
}

function viewCart() {
    return JSON.parse(sessionStorage.getItem('cart')) || [];
}
  • 会话级别的用户偏好设置:如临时的主题选择或语言切换等
function saveTheme(theme) {
    sessionStorage.setItem('theme', theme);
}

function loadTheme() {
    return sessionStorage.getItem('theme') || 'light';  // 默认为浅色主题
}

2.4 注意事项

使用sessionStorage时需注意以下几点:

  • 会话依赖性:sessionStorage数据仅在当前页面会话期间有效,关闭浏览器标签或窗口后数据会被清除。这意味着其不适合长期存储重要数据。
  • 同源策略:sessionStorage数据仅在同一协议、域名和端口下可见,这有助于保护用户隐私,但也意味着不同网站之间无法共享数据。
  • 容量限制:这是各Web存储策略共同存在的问题,尽管大多数现代浏览器提供了较大的存储空间(约5MB),但当接近上限时,可能会触发警告或错误。合理规划存储内容非常重要。
  • 跨窗口同步问题:sessionStorage是基于各浏览器标签页或窗口独立的存储机制,这意味着不同标签页或窗口之间的sessionStorage是完全隔离的,一个标签页无法直接访问另一个标签页的sessionStorage数据。即使多个标签页打开的是完全相同的URL,每个标签页的sessionStorage仍然是独立的。
    • 需要注意的是,由于sessionStorage的这种独立性,其不支持跨页面通信,亦无法通过监听storage事件来实现跨窗口同步。若需要在多个标签页间共享或同步数据,应考虑使用localStorage或者其他解决方案,例如IndexedDB或通过服务器端进行数据同步。

3 Cookie

Cookie是一种存储于客户端(通常是用户的浏览器)的数据片段,允许网站在用户访问期间或之后记住某些信息。这些信息可以是简单的偏好设置,亦可以是复杂的会话标识符。

特点:

  • 每次请求都会自动发送给服务器:这意味着Cookie中的数据会在每个HTTP请求中被发送回服务器,增加了网络流量。
  • 大小限制约为4KB:单个域名下的所有Cookie的总大小通常不超过4KB。
  • 支持设置过期时间:可以设置Cookie的有效期,过期后会被自动删除。
  • 安全性选项:可设置SecureHttpOnly标志增强安全性。
  • 同源策略:Cookie数据仅在同一协议、域名和端口下可见。

3.1 基本操作

Cookie是一串特殊的字符串,可通过document.cookie来读取、写入和删除Cookie:

  1. 设置Cookie:直接给document.cookie赋值来设置一个新Cookie,需要指定名称、值以及可选的属性如过期时间、路径等
    • 注:expires参数指定了Cookie的过期日期,若不设置,则Cookie将被视为会话Cookie,在关闭浏览器时自动删除;path参数指定了Cookie可用的路径,默认为/
// 设置一个名为username的Cookie,值为Akira Syma,并设置过期时间为一年
document.cookie = "username=Akira Syma; expires=" + new Date(2026, 3, 2).toUTCString() + "; path=/";
  1. 获取Cookie:直接使用document.cookie可获取所有Cookie,返回的是一个包含所有Cookie的字符串,各Cookie之间用分号加空格隔开。通常还需编写辅助函数来解析特定的Cookie
// 获取全部Cookie
console.log(document.cookie);   // 输出:"username=Akira Syma"

// 获取指定Cookie
function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

console.log(getCookie('username'));   // 输出:Akira Syma
  1. 删除Cookie:通过将Cookie的过期时间设置为过去的时间来删除Cookie
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";

3.2 安全性和隐私保护

为了提高安全性,Cookie提供了几个重要的标志:

  1. Secure:若设置了该标志,则Cookie只能通过HTTPS协议传输,不能通过HTTP传输,这有助于防止中间人攻击
document.cookie = "username=Akira Syma; Secure; path=/";
  1. HttpOnly:若设置了该标志,则JS代码无法访问该Cookie,只能通过HTTP(S)请求发送到服务器,这有助于防御XSS攻击
document.cookie = "sessionToken=abc123xyz; HttpOnly; path=/";
  1. SameSite:控制是否可以在跨站请求中携带Cookie,可取3种值——StrictLaxNone,其中None必须与Secure标志一起使用
document.cookie = "sessionToken=abc123xyz; SameSite=Strict; path=/";

3.3 应用示例

Cookie曾在许多场景中都有广泛应用,以下是几个典型的应用示例:

  • 会话管理:存储会话标识符(Session ID),以便服务器能够识别用户并在多个页面请求之间保持登录状态
// 设置Session ID
document.cookie = "sessionId=abc123xyz; path=/";

// 获取Session ID
const sessionId = getCookie('sessionId');
  • 用户偏好设置:Cookie亦能用于记住用户的语言选择、主题颜色等偏好设置
// 设置用户语言偏好
document.cookie = "preferredLanguage=en; expires=" + new Date(2026, 3, 2).toUTCString() + "; path=/";

// 获取用户语言偏好
const language = getCookie('preferredLanguage') || 'en';
  • 购物车信息:Cookie亦能用于暂时存储用户的购物车内容,直至其完成购买或主动清空购物车
// 添加商品到购物车
function addToCart(item) {
    let cart = JSON.parse(getCookie('cart')) || [];
    cart.push(item);
    document.cookie = `cart=${JSON.stringify(cart)}; path=/`;
}

// 查看购物车
function viewCart() {
    return JSON.parse(getCookie('cart')) || [];
}

3.4 注意事项

使用Cookie时需注意以下几点:

  • 隐私问题:用户可能会对网站存储过多的个人信息感到不安,因此应尽量减少不必要的Cookie使用,并确保遵守相关的隐私政策和法规。
  • 性能影响:每次HTTP请求都会发送所有的Cookie,因此应尽量减小Cookie的大小,并避免不必要的Cookie发送。
  • 安全性考虑:对于敏感信息,建议使用SecureHttpOnly标志,并结合SameSite属性来防止CSRF和XSS攻击。

4 总结

特性 localStorage sessionStorage Cookie
存储大小 约5MB 约5MB 约4KB
有效期 永久 页面会话期间 可设置
作用域 同源 同源 同源
传输到服务器 不传输 不传输 自动传输
使用场景 用户偏好设置 表单数据暂存 登录状态跟踪

发表评论