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 的属性、适用场景。
相关推荐
前端之虎陈随易14 小时前
2年没用Nodejs了,Bun很香
linux·前端·javascript·vue.js·typescript
好运的阿财15 小时前
OpenClaw工具拆解之host_workspace_write+host_workspace_edit
前端·javascript·人工智能·机器学习·ai编程·openclaw·openclaw工具
XiYang-DING15 小时前
JavaScript
开发语言·javascript·ecmascript
空中海16 小时前
02 React Native状态、导航、数据流与设备能力
javascript·react native·react.js
空中海17 小时前
02 状态、Hooks、副作用与数据流
开发语言·javascript·ecmascript
空中海17 小时前
04 React Native工程化、质量、发布与生态选型
javascript·react native·react.js
杨超凡18 小时前
豆包收费了?我特么自己用“意念”搓了一个!
javascript
threelab19 小时前
Three.js 咖啡杯烟雾效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
Heo19 小时前
14_React 中的更新队列 updateQueue
前端·javascript·面试