JS 入门通关手册(48):本地存储全解析(localStorage/sessionStorage/cookie,面试高频)

摘要

本文全面梳理前端本地存储的三大核心方案 ------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.comhttps://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)核心特性(与前两者差异较大,必记)
  1. 存储大小限制:约 4KB,仅能存储少量数据。
  2. 过期时间:可通过 expiresmax-age 设置过期时间,默认会话结束后过期。
  3. 随请求发送:每次 HTTP 请求(同域),都会自动将 cookie 携带到服务器,无需手动处理。
  4. 作用域:可通过 domain(域名)和 path(路径)设置作用域,实现跨子域共享。
  5. 安全性:可设置 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),否则会乱码。

四、本地存储实战场景汇总(真实项目常用)

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. 避坑指南

  1. 不存储敏感数据:密码、token(未设置 httpOnly)、银行卡号 等敏感数据,禁止存储在 localStorage、sessionStorage;cookie 存储敏感数据时,必须设置 httpOnlysecure
  2. 数据加密:存储非敏感但重要的数据时(如用户偏好),可进行简单加密(如 base64 编码),降低被篡改的风险。
  3. 限制存储容量:localStorage、sessionStorage 不超过 5MB,cookie 不超过 4KB,避免存储过多数据影响性能。
  4. 清理过期数据:localStorage 永久存储,需手动清理无用数据;cookie 设置合理的过期时间,避免长期存储。
  5. 同源限制:注意同源策略,不同源页面无法共享本地存储数据,跨域场景需通过后端配合实现数据共享。

六、高频面试题(必背标准答案)

  1. **localStorage、sessionStorage、cookie 的区别是什么?(核心面试题)**答:① 存储大小:localStorage/sessionStorage 约 5MB,cookie 约 4KB;② 过期时间:localStorage 永久,sessionStorage 会话结束,cookie 可设置过期时间;③ 作用域:localStorage 同源所有标签页共享,sessionStorage 仅当前标签页,cookie 同源可设置作用域;④ 服务器交互:cookie 自动携带到服务器,前两者不主动发送;⑤ 操作难度:localStorage/sessionStorage 简单,cookie 繁琐。

  2. localStorage 如何存储对象?为什么? 答:localStorage 只能存储字符串,存储对象时,需用 JSON.stringify() 将对象序列化为字符串,获取时用 JSON.parse() 反序列化;因为 localStorage 的 value 必须是字符串类型,非字符串会被自动转为字符串,直接存储对象会变成 "[object Object]",无法正常读取。

  3. **cookie 的 httpOnly 和 secure 属性有什么作用?**答:① httpOnly:禁止 JS 读取 cookie,防止 XSS 攻击,保护 cookie 中的敏感数据(如 token);② secure:仅在 HTTPS 协议下,cookie 才会生效并随请求发送,防止 HTTP 协议下数据被窃取。

  4. **什么时候用 localStorage、sessionStorage、cookie?**答:① localStorage:存储永久、非敏感的全局数据(如用户主题、记住的用户名);② sessionStorage:存储当前会话的临时数据(如表单临时输入、页面跳转临时数据);③ cookie:存储需随请求发送到服务器的数据(如登录 token)、少量会话数据。

  5. **localStorage 会跨域共享吗?为什么?**答:不会;localStorage 遵循同源策略,只有协议、域名、端口完全一致的页面,才能共享 localStorage 数据;不同源页面(如 http 和 https、不同域名),无法访问彼此的 localStorage。

  6. **sessionStorage 关闭标签页后数据会丢失吗?同一浏览器不同标签页能共享吗?**答:① 会丢失,sessionStorage 是会话级存储,关闭标签页或浏览器后,数据自动清除;② 不能共享,同一浏览器的不同标签页(即使同源),sessionStorage 数据相互独立,无法共享。


七、总结(核心要点速记)

  1. 本地存储三大方案:localStorage(永久、全局)、sessionStorage(会话、当前标签页)、cookie(小容量、随请求发送)。
  2. 核心区别:存储大小、过期时间、作用域、与服务器的交互方式。
  3. 实战选型:永久数据用 localStorage,临时数据用 sessionStorage,需传服务器的数据用 cookie。
  4. 安全注意:不存敏感数据,cookie 敏感数据需设 httpOnly/secure,避免 XSS/CSRF 攻击。
  5. 面试重点:三者区别、存储对象的方法、cookie 的属性、适用场景。
相关推荐
玄空z2 小时前
通俗理解 RAG 与微调:给大模型“翻书”还是“洗脑”
javascript
Devin_chen2 小时前
单例模式渐进式学习指南
前端·javascript
阿民_armin3 小时前
使用 IntersectionObserver + 哨兵元素实现长列表懒加载
前端·javascript·vue.js
ouzz3 小时前
使用 react-canvas 制作一个 Figma 工具:从画布到编辑器
前端·javascript
颜酱3 小时前
语音合成与视觉模型api接入实现
前端·javascript·人工智能
阿珊和她的猫4 小时前
使用 TypeScript 实现数组类型判断方法
javascript·typescript·状态模式
XTTX1104 小时前
Vue3+Cesium电子围栏效果
前端·javascript·vue.js
小高0075 小时前
🔥前端性能内卷终点?Signals 正在重塑我们的开发习惯
前端·javascript·vue.js
LXXgalaxy6 小时前
Vue3 列表数据流:从赋值入门到进阶(独立学习版)
javascript·vue.js·学习