摘要
本文全面梳理前端本地存储的三大核心方案 ------localStorage、sessionStorage、cookie,详细讲解三者的定义、常用 API、存储特性、适用场景,对比三者的核心区别,拆解实战用法与避坑技巧,覆盖面试高频考点(存储区别、过期策略、安全问题),结合用户信息存储、记住密码、会话状态保持等真实业务场景,帮助开发者熟练选择并运用本地存储方案,规避安全隐患,轻松应对前端面试。
一、前言:为什么需要本地存储?
前端开发中,我们经常需要在浏览器中存储少量数据,比如用户登录状态、记住密码、页面偏好设置(如主题、字体大小)、临时会话数据等。如果不使用本地存储,这些数据会在页面刷新、浏览器关闭后丢失,需要每次重新请求服务器或让用户重新输入,严重影响用户体验。
本地存储是浏览器提供的 "本地数据缓存" 功能,无需请求服务器,可直接在浏览器中读写数据,提升页面响应速度和用户体验。而 localStorage、sessionStorage、cookie 是前端最常用的三种本地存储方案,三者各有特点、适用场景不同,也是前端面试的高频考点 ------ 几乎所有中高级前端面试,都会考查三者的区别与使用场景。
很多开发者在使用本地存储时,容易混淆三者的特性,比如不清楚 "sessionStorage 关闭标签就丢失""cookie 有过期时间",导致使用场景错误、出现数据泄露或数据丢失问题。掌握这三种存储方案的核心区别与最佳实践,是前端开发的必备能力。
二、本地存储核心概念(必懂)
1. 本地存储定义
本地存储是浏览器提供的一种在客户端(浏览器)保存数据的机制,数据存储在用户本地,无需与服务器交互,可直接通过 JavaScript 读写,适用于存储少量、非敏感的临时数据或偏好设置。
2. 三大本地存储方案对比(面试必背)
表格
| 对比项 | localStorage(本地存储) | sessionStorage(会话存储) | cookie(Cookie) |
|---|---|---|---|
| 存储大小 | 约 5MB | 约 5MB | 约 4KB(最小) |
| 过期时间 | 永久存储(除非手动删除) | 会话结束(关闭浏览器 / 标签页) | 可设置过期时间(默认会话结束) |
| 作用域 | 同源(协议、域名、端口一致),所有标签页共享 | 同源,仅当前标签页有效(不共享) | 同源,所有标签页共享,可设置 domain、path 扩大作用域 |
| 通信能力 | 无法跨域访问 | 无法跨域访问 | 可通过请求头携带,实现跨域(需配置) |
| 服务器交互 | 不主动发送到服务器 | 不主动发送到服务器 | 每次 HTTP 请求都会自动携带到服务器 |
| 操作方式 | 简单(JS 直接读写) | 简单(JS 直接读写) | 需通过 JS 或服务器设置,操作较繁琐 |
| 安全性 | 一般(易被篡改,不存敏感数据) | 一般(仅当前标签页,相对安全) | 可设置 httpOnly、secure,相对更安全 |
一句话记忆:localStorage 永久存、sessionStorage 会话存、cookie 小容量可随请求发。
三、三大本地存储方案详解(实战必备)
1. localStorage(本地存储,最常用)
localStorage 是最常用的本地存储方案,用于永久存储同源页面的少量数据,数据不会随浏览器关闭而丢失,除非手动删除(代码删除或浏览器清除缓存)。
(1)核心 API(简单易用,必记)
javascript
运行
javascript
// 1. 存储数据(key-value格式,value必须是字符串,非字符串会自动转为字符串)
localStorage.setItem("username", "张三"); // 存储字符串
localStorage.setItem("age", 20); // 自动转为字符串"20"
localStorage.setItem("user", JSON.stringify({ name: "张三", age: 20 })); // 存储对象(需序列化)
// 2. 获取数据(返回字符串,对象需反序列化)
const username = localStorage.getItem("username"); // "张三"
const age = localStorage.getItem("age"); // "20"(需手动转为数字)
const user = JSON.parse(localStorage.getItem("user")); // 反序列化,得到对象
// 3. 删除指定数据
localStorage.removeItem("age");
// 4. 清空所有localStorage数据
localStorage.clear();
// 5. 获取所有存储的key(返回类数组)
const keys = localStorage.key(); // 获取第一个key
const allKeys = Object.keys(localStorage); // 获取所有key,转为数组
(2)实战场景:存储用户偏好设置
javascript
运行
javascript
// 存储用户主题设置(暗黑模式/浅色模式)
function setTheme(theme) {
// 存储主题值
localStorage.setItem("theme", theme);
// 应用主题
document.documentElement.className = theme;
}
// 页面加载时,读取主题设置
window.onload = function() {
// 读取存储的主题,默认浅色模式
const theme = localStorage.getItem("theme") || "light";
setTheme(theme);
};
// 切换主题(点击按钮)
document.querySelector("#themeBtn").addEventListener("click", () => {
const currentTheme = localStorage.getItem("theme") || "light";
const newTheme = currentTheme === "light" ? "dark" : "light";
setTheme(newTheme);
});
避坑点
- localStorage 存储的 value 必须是字符串 ,存储对象、数组时,需用
JSON.stringify()序列化,获取时用JSON.parse()反序列化。 - 数据是永久存储,即使关闭浏览器、重启电脑,数据依然存在,需手动删除。
- 同源限制:只有协议、域名、端口完全一致的页面,才能共享 localStorage 数据(如http://xxx.com和https://xxx.com不同源,无法共享)。
- 不能存储敏感数据(如密码、token),易被篡改和读取。
2. sessionStorage(会话存储)
sessionStorage 用于存储当前会话(当前标签页)的临时数据,数据仅在当前标签页有效,关闭标签页或浏览器后,数据自动丢失;同一浏览器的不同标签页(即使同源),也无法共享 sessionStorage 数据。
(1)核心 API(与 localStorage 完全一致)
javascript
运行
javascript
// 1. 存储数据
sessionStorage.setItem("tempData", "临时数据");
sessionStorage.setItem("formData", JSON.stringify({ username: "", password: "" }));
// 2. 获取数据
const tempData = sessionStorage.getItem("tempData");
const formData = JSON.parse(sessionStorage.getItem("formData"));
// 3. 删除指定数据
sessionStorage.removeItem("tempData");
// 4. 清空所有数据
sessionStorage.clear();
(2)实战场景:存储表单临时数据(防止刷新丢失)
javascript
运行
javascript
// 监听表单输入,实时存储临时数据
const form = document.querySelector("#loginForm");
const usernameInput = form.querySelector('input[name="username"]');
const passwordInput = form.querySelector('input[name="password"]');
// 页面加载时,恢复表单数据(如果有)
window.onload = function() {
const formData = JSON.parse(sessionStorage.getItem("formData")) || {};
usernameInput.value = formData.username || "";
passwordInput.value = formData.password || "";
};
// 输入时实时存储
form.addEventListener("input", () => {
const formData = {
username: usernameInput.value,
password: passwordInput.value
};
sessionStorage.setItem("formData", JSON.stringify(formData));
});
// 表单提交后,清空临时数据
form.addEventListener("submit", (e) => {
e.preventDefault();
// 提交逻辑...
sessionStorage.removeItem("formData"); // 提交成功,清空临时数据
});
避坑点
- sessionStorage 仅在当前标签页有效,打开新标签页、刷新当前标签页(不关闭),数据依然存在;关闭标签页后,数据立即丢失。
- 同一浏览器的不同标签页(即使同源),sessionStorage 数据不共享(如打开两个百度标签页,各自的 sessionStorage 独立)。
- 存储规则与 localStorage 一致:value 必须是字符串,需序列化对象 / 数组。
3. cookie(Cookie,传统存储方案)
cookie 是最早的本地存储方案,用于存储少量、需随 HTTP 请求发送到服务器的数据(如用户登录凭证),存储容量最小(约 4KB),可设置过期时间,每次请求都会自动携带到服务器。
(1)核心特性(与前两者差异较大,必记)
- 存储大小限制:约 4KB,仅能存储少量数据。
- 过期时间:可通过
expires或max-age设置过期时间,默认会话结束后过期。 - 随请求发送:每次 HTTP 请求(同域),都会自动将 cookie 携带到服务器,无需手动处理。
- 作用域:可通过
domain(域名)和path(路径)设置作用域,实现跨子域共享。 - 安全性:可设置
httpOnly(禁止 JS 读取,防止 XSS 攻击)、secure(仅 HTTPS 协议下有效)。
(2)操作 cookie(JS 操作,较繁琐)
cookie 没有像 localStorage 那样简洁的 API,需手动封装函数实现读写删除。
javascript
运行
javascript
// 1. 封装:设置cookie(key, value, 过期时间/天)
function setCookie(key, value, days = 7) {
// 处理过期时间
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
const expires = `expires=${date.toUTCString()}`;
// 存储cookie(value需编码,处理中文)
document.cookie = `${key}=${encodeURIComponent(value)}; ${expires}; path=/`;
}
// 2. 封装:获取cookie(根据key)
function getCookie(key) {
// 分割cookie字符串
const cookies = document.cookie.split("; ");
for (let cookie of cookies) {
const [cookieKey, cookieValue] = cookie.split("=");
if (cookieKey === key) {
// 解码,处理中文
return decodeURIComponent(cookieValue);
}
}
return null; // 未找到对应cookie
}
// 3. 封装:删除cookie(设置过期时间为过去)
function removeCookie(key) {
// 设置过期时间为昨天,自动删除
setCookie(key, "", -1);
}
// 使用示例
setCookie("token", "abc123", 7); // 存储token,7天过期
const token = getCookie("token"); // 获取token
removeCookie("token"); // 删除token
(3)服务器设置 cookie(补充,面试可能提及)
除了 JS,服务器也可以通过 HTTP 响应头 Set-Cookie 设置 cookie,这是最常用的方式(如用户登录后,服务器返回 cookie 存储登录状态)。
示例(后端响应头):
plaintext
Set-Cookie: token=abc123; expires=Wed, 10 Apr 2027 08:00:00 GMT; path=/; domain=example.com; httpOnly; secure
(4)实战场景:存储用户登录凭证(token)
javascript
运行
javascript
// 登录成功后,存储token(服务器返回token)
function loginSuccess(token) {
// 存储token到cookie,7天过期,设置httpOnly(需服务器设置)
// JS无法设置httpOnly,需后端配合
setCookie("token", token, 7);
// 跳转到首页
location.href = "./index.html";
}
// 页面加载时,验证登录状态
window.onload = function() {
const token = getCookie("token");
if (!token) {
// 无token,跳转到登录页
location.href = "./login.html";
}
};
// 退出登录,删除token
function logout() {
removeCookie("token");
location.href = "./login.html";
}
避坑点
- cookie 存储容量小(4KB),仅适合存储少量数据(如 token、用户 ID)。
- 每次 HTTP 请求都会自动携带 cookie,过多 cookie 会增加请求体积,影响页面加载速度。
- JS 可读取未设置 httpOnly 的 cookie,存在 XSS 安全风险;设置 httpOnly 后,JS 无法读取,更安全(需后端配合)。
- 中文 cookie 需编码(encodeURIComponent)和解码(decodeURIComponent),否则会乱码。
四、本地存储实战场景汇总(真实项目常用)
场景 1:记住密码(localStorage + cookie 结合)
javascript
运行
javascript
// 登录页面,记住密码勾选框
const rememberBtn = document.querySelector("#remember");
const usernameInput = document.querySelector("#username");
const passwordInput = document.querySelector("#password");
// 页面加载时,读取记住的密码(localStorage存储,cookie存储token)
window.onload = function() {
const remember = localStorage.getItem("remember") === "true";
if (remember) {
const username = localStorage.getItem("username");
usernameInput.value = username;
rememberBtn.checked = true;
}
};
// 登录提交
function login() {
const username = usernameInput.value;
const password = passwordInput.value;
const remember = rememberBtn.checked;
// 模拟登录请求,获取token
const token = "abc123456";
// 存储token到cookie(7天过期)
setCookie("token", token, 7);
// 如果勾选记住密码,存储用户名到localStorage
if (remember) {
localStorage.setItem("username", username);
localStorage.setItem("remember", "true");
} else {
// 取消记住,删除localStorage数据
localStorage.removeItem("username");
localStorage.removeItem("remember");
}
// 跳转到首页
location.href = "./index.html";
}
场景 2:临时会话数据存储(sessionStorage)
javascript
运行
javascript
// 列表页,点击详情,存储临时数据,跳转详情页
const listItems = document.querySelectorAll(".list-item");
listItems.forEach(item => {
item.addEventListener("click", () => {
const itemData = {
id: item.dataset.id,
name: item.dataset.name,
price: item.dataset.price
};
// 存储临时数据到sessionStorage
sessionStorage.setItem("itemDetail", JSON.stringify(itemData));
// 跳转详情页
location.href = "./detail.html";
});
});
// 详情页,读取临时数据
window.onload = function() {
const itemData = JSON.parse(sessionStorage.getItem("itemDetail")) || {};
if (!itemData.id) {
// 无临时数据,跳回列表页
location.href = "./list.html";
return;
}
// 渲染详情页数据
document.querySelector(".item-name").textContent = itemData.name;
document.querySelector(".item-price").textContent = itemData.price;
};
场景 3:用户主题切换(localStorage)
javascript
运行
javascript
// 主题切换按钮
const themeBtns = document.querySelectorAll(".theme-btn");
const html = document.documentElement;
// 页面加载,读取主题
window.onload = function() {
const theme = localStorage.getItem("theme") || "default";
html.className = theme;
// 切换按钮状态
themeBtns.forEach(btn => {
if (btn.dataset.theme === theme) {
btn.classList.add("active");
}
});
};
// 点击切换主题
themeBtns.forEach(btn => {
btn.addEventListener("click", () => {
const theme = btn.dataset.theme;
// 存储主题到localStorage
localStorage.setItem("theme", theme);
// 应用主题
html.className = theme;
// 切换按钮状态
themeBtns.forEach(b => b.classList.remove("active"));
btn.classList.add("active");
});
});
五、本地存储安全问题与避坑指南(面试必提)
1. 安全风险
- XSS 攻击:localStorage、sessionStorage 可被 JS 读取和篡改,若页面存在 XSS 漏洞,攻击者可窃取存储的数据(如用户信息);未设置 httpOnly 的 cookie,也会被 JS 窃取。
- CSRF 攻击:cookie 会自动随请求发送,若页面存在 CSRF 漏洞,攻击者可利用 cookie 伪造请求,操作用户账号。
- 数据泄露:本地存储的数据存储在用户本地,若用户使用公共设备(如网吧电脑),未清除缓存,数据可能被他人获取。
2. 避坑指南
- 不存储敏感数据:密码、token(未设置 httpOnly)、银行卡号 等敏感数据,禁止存储在 localStorage、sessionStorage;cookie 存储敏感数据时,必须设置
httpOnly和secure。 - 数据加密:存储非敏感但重要的数据时(如用户偏好),可进行简单加密(如 base64 编码),降低被篡改的风险。
- 限制存储容量:localStorage、sessionStorage 不超过 5MB,cookie 不超过 4KB,避免存储过多数据影响性能。
- 清理过期数据:localStorage 永久存储,需手动清理无用数据;cookie 设置合理的过期时间,避免长期存储。
- 同源限制:注意同源策略,不同源页面无法共享本地存储数据,跨域场景需通过后端配合实现数据共享。
六、高频面试题(必背标准答案)
-
**localStorage、sessionStorage、cookie 的区别是什么?(核心面试题)**答:① 存储大小:localStorage/sessionStorage 约 5MB,cookie 约 4KB;② 过期时间:localStorage 永久,sessionStorage 会话结束,cookie 可设置过期时间;③ 作用域:localStorage 同源所有标签页共享,sessionStorage 仅当前标签页,cookie 同源可设置作用域;④ 服务器交互:cookie 自动携带到服务器,前两者不主动发送;⑤ 操作难度:localStorage/sessionStorage 简单,cookie 繁琐。
-
localStorage 如何存储对象?为什么? 答:localStorage 只能存储字符串,存储对象时,需用
JSON.stringify()将对象序列化为字符串,获取时用JSON.parse()反序列化;因为 localStorage 的 value 必须是字符串类型,非字符串会被自动转为字符串,直接存储对象会变成 "[object Object]",无法正常读取。 -
**cookie 的 httpOnly 和 secure 属性有什么作用?**答:① httpOnly:禁止 JS 读取 cookie,防止 XSS 攻击,保护 cookie 中的敏感数据(如 token);② secure:仅在 HTTPS 协议下,cookie 才会生效并随请求发送,防止 HTTP 协议下数据被窃取。
-
**什么时候用 localStorage、sessionStorage、cookie?**答:① localStorage:存储永久、非敏感的全局数据(如用户主题、记住的用户名);② sessionStorage:存储当前会话的临时数据(如表单临时输入、页面跳转临时数据);③ cookie:存储需随请求发送到服务器的数据(如登录 token)、少量会话数据。
-
**localStorage 会跨域共享吗?为什么?**答:不会;localStorage 遵循同源策略,只有协议、域名、端口完全一致的页面,才能共享 localStorage 数据;不同源页面(如 http 和 https、不同域名),无法访问彼此的 localStorage。
-
**sessionStorage 关闭标签页后数据会丢失吗?同一浏览器不同标签页能共享吗?**答:① 会丢失,sessionStorage 是会话级存储,关闭标签页或浏览器后,数据自动清除;② 不能共享,同一浏览器的不同标签页(即使同源),sessionStorage 数据相互独立,无法共享。
七、总结(核心要点速记)
- 本地存储三大方案:localStorage(永久、全局)、sessionStorage(会话、当前标签页)、cookie(小容量、随请求发送)。
- 核心区别:存储大小、过期时间、作用域、与服务器的交互方式。
- 实战选型:永久数据用 localStorage,临时数据用 sessionStorage,需传服务器的数据用 cookie。
- 安全注意:不存敏感数据,cookie 敏感数据需设 httpOnly/secure,避免 XSS/CSRF 攻击。
- 面试重点:三者区别、存储对象的方法、cookie 的属性、适用场景。