Skip to content

JavaScript Cookies

JavaScript 客户端存储:Cookie 与 Web Storage

Section titled “JavaScript 客户端存储:Cookie 与 Web Storage”

JavaScript 提供了多种在客户端(用户的浏览器中)存储用户信息和应用程序数据的方式。传统的方法是 Cookie,而现代浏览器则提供了 Web Storage API(包括 localStorage 和 sessionStorage),这对于许多用例来说通常更简单。

Cookie 是小块数据,由用户的 Web 浏览器以文本文件形式存储在用户的计算机上。它们与特定的网站相关联。

最初,Cookie 设计用于帮助网站记住用户跨多个页面视图或访问的信息,因为 HTTP 是一种无状态协议(这意味着每个请求都是独立的,服务器本身不会记住过去的交互)。

  • 当用户访问网页时,信息(如用户名或偏好设置)可以存储在 Cookie 中。
  • 下次用户访问该页面(或同一域上的另一个页面)时,浏览器会将相关的 Cookie 发送回服务器,使网站能够“记住”用户或他们的设置。

Cookie 以名值对(name-value pairs)的形式保存,例如 username=john_doe。

虽然 JavaScript 可以与 Cookie 交互,但需要注意的是,Cookie 会随着每次发送到其所属域的 HTTP 请求一起发送,如果 Cookie 较大或数量较多,可能会影响性能。

JavaScript 可以使用 document.cookie 属性创建、读取和删除 Cookie。但是,这个 API 比较原始。

要创建或更新 Cookie,你可以将一个包含名值对以及可选属性(如 expires、max-age、path、domain、secure 和 samesite)的字符串赋值给 document.cookie。

// 基本 Cookie
document.cookie = "username=john_doe";
// 带有过期日期 (UTC) 和路径的 Cookie
const expiryDate = new Date();
expiryDate.setTime(expiryDate.getTime() + (7 * 24 * 60 * 60 * 1000)); // 从现在算起 7 天
document.cookie = `userId=123; expires=${expiryDate.toUTCString()}; path=/`;
// 带有 max-age(以秒为单位)、secure 和 samesite 属性的 Cookie
// 'secure' 表示该 Cookie 仅通过 HTTPS 发送
// 'samesite=strict' 有助于防止 CSRF 攻击
document.cookie = "sessionToken=abcxyz; max-age=86400; path=/; secure; samesite=strict";

重要的 Cookie 属性:

  • expires=UTCString:设置过期日期。如果省略,则为会话 Cookie(浏览器关闭时删除)。
  • max-age=seconds:比 expires 更推荐。设置从现在算起的过期时间(以秒为单位)。
  • path=pathValue:指定 Cookie 有效的 URL 路径(例如 /、/app)。
  • domain=domainValue:指定 Cookie 有效的域。
  • secure:如果存在,Cookie 仅通过 HTTPS 发送。
  • samesite=Strict|Lax|None:控制跨站请求行为,用于 CSRF 防护。

读取 document.cookie 会返回一个字符串,包含当前文档所有可访问的 Cookie,它们之间用分号分隔(例如 cookie1=value1; cookie2=value2)。你需要解析这个字符串来获取特定 Cookie 的值。

const allCookies = document.cookie;
console.log(allCookies);

要删除 Cookie,可以将其 expires 属性设置为一个过去的日期,或者将 max-age 设置为 0 或负数。你还必须指定设置 Cookie 时使用的相同的 path 和 domain 属性。

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/";
// or using max-age
document.cookie = "userId=; max-age=0; path=/";

由于 document.cookie API 比较底层,因此经常使用辅助函数:

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 = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
}
function getCookie(name) {
const nameEQ = encodeURIComponent(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(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
}
return null;
}
function deleteCookie(name) {
document.cookie = encodeURIComponent(name) + '=; Max-Age=-99999999; path=/';
}
// 使用方法:
// setCookie("userPreference", "darkMode", 30);
// const pref = getCookie("userPreference");
// if (pref === "darkMode") { /* 应用深色模式 */ }
// deleteCookie("userPreference");

现代替代方案:Web Storage API(localStorage 和 sessionStorage)

Section titled “现代替代方案:Web Storage API(localStorage 和 sessionStorage)”

对于许多不需要在每个请求中将数据发送到服务器的客户端存储需求,Web Storage API 是一个更现代且通常更简单的解决方案。与 Cookie(约 4KB)相比,它提供了明显更多的存储容量(通常每个源(origin)5-10MB)。

存储没有过期日期的数据。即使浏览器窗口关闭后重新打开,数据仍然可用,直到被 JavaScript 或用户明确删除。

// 存储数据
localStorage.setItem('theme', 'dark');
localStorage.setItem('user', JSON.stringify({ name: 'Alice', id: 1 }));
// 检索数据
const theme = localStorage.getItem('theme');
const user = JSON.parse(localStorage.getItem('user'));
console.log(theme); // "dark"
console.log(user.name); // "Alice"
// 删除特定项
localStorage.removeItem('theme');
// 清除源(origin)的所有项
// localStorage.clear();

存储仅在当前浏览器会话期间有效的数据。当标签页或浏览器窗口关闭时,数据将被清除。

// 存储数据
sessionStorage.setItem('tempData', 'This will be gone after session ends');
// 检索数据
const tempData = sessionStorage.getItem('tempData');
console.log(tempData);

Cookie 与 Web Storage 的主要区别:

  • 服务器交互:Cookie 会随着发送到其域的每个 HTTP 请求一起发送。Web Storage 数据不会自动发送到服务器。
  • 存储容量:Web Storage (5-10MB) > Cookie (~4KB)。
  • API 简洁性:Web Storage API(setItem、getItem、removeItem)通常比解析 document.cookie 更易于使用。
  • 数据类型:Web Storage 只存储字符串。对于对象或数组,需要使用 JSON.stringify() 存储,使用 JSON.parse() 检索。
  • 可访问性:Cookie 可以被服务器端和客户端脚本访问(除非设置了 HttpOnly 标志)。Web Storage 纯粹是客户端的。
明智选择:当数据需要随请求发送到服务器时(例如会话 ID),使用 Cookie。对于持久化的客户端存储(例如用户偏好设置、离线数据),使用 localStorage。对于临时的、特定于会话的数据(例如提交前的表单数据),使用 sessionStorage。