登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  前端

Web Storage 为什么 localStorage 不能保存对象

来源:17golang原创

时间:2026-10-26 05:45:08 283浏览 收藏

localStorage的键和值都是字符串,不能直接保留JavaScript对象结构。把普通对象直接传给setItem,通常会存成[object Object];正确方式是先JSON.stringify,再在读取后JSON.parse,并确认解析结果符合应用需要的结构。

参考文档地址:https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

触发信号:读回的是字符串而不是配置对象

设想一个文章列表页把主题和每页条数保存为配置,页面刷新后却读不到theme字段。若写入时传的是普通对象,问题往往发生在字符串转换阶段,而不是刷新清除了对象。下面是原创的配置存取场景,未在浏览器执行,也不涉及真实用户信息。

const settings = { theme: "dark", pageSize: 20 };
// 错误示范:setItem会把普通对象转换为字符串。
localStorage.setItem("demo:raw-settings", settings);
const raw = localStorage.getItem("demo:raw-settings");
console.log(typeof raw); // 有值时读回类型为string。

以上错误示范使用独立演示键,说明API的值类型。localStorage不是对象引用仓库;保存以后继续修改内存对象,也不会自动更新已经存进去的文本。

内存对象与localStorage字符串存储边界结构说明图
结构说明图:内存对象、JSON文本和字符串存储具有不同表示形式;不是开发者工具截图。

快速判断:区分转换问题和存储不可用

信号判断方向
出现[object Object]写入前缺少明确的JSON编码
getItem返回null该来源下此键不存在,不代表解析失败
JSON.parse抛SyntaxError已保存文本不是合法JSON
访问或写入抛异常检查策略限制、配额与运行环境

HTTP与HTTPS、不同主机或端口分别属于不同来源,不能假设它们共用同一份localStorage。file:页面的行为也不应作为正式应用依据。隐私浏览、用户清理数据或存储策略会影响保留行为,不能把无内置过期时间理解为永久可靠备份。

处理步骤:保存JSON并恢复有限字段

示例只保存可重新构造的显示偏好。使用版本字段和固定字段检查,避免把解析出的任意对象直接合并到运行时配置。把以下代码作为页面脚本使用,浏览器需允许当前来源访问Web Storage。

const SETTINGS_KEY = "article-list:settings";
const defaults = () => ({ theme: "light", pageSize: 20 });

function isSettings(value) {
  // JSON合法不代表业务结构正确,只接受约定字段类型和范围。
  return value !== null && typeof value === "object"
    && !Array.isArray(value) && value.version === 1
    && ["light", "dark"].includes(value.theme)
    && [10, 20, 50].includes(value.pageSize);
}

function readSettings() {
  try {
    const raw = localStorage.getItem(SETTINGS_KEY);
    if (raw === null) return { value: defaults(), reason: "missing" };
    const parsed = JSON.parse(raw);
    if (!isSettings(parsed)) {
      return { value: defaults(), reason: "unsupported-data" };
    }
    // 重新构造需要的字段,不复用或合并不可信额外属性。
    return {
      value: { theme: parsed.theme, pageSize: parsed.pageSize },
      reason: "loaded",
    };
  } catch (error) {
    return {
      value: defaults(),
      reason: error instanceof SyntaxError ? "invalid-json" : "read-failed",
    };
  }
}

function saveSettings(value) {
  const payload = {
    version: 1, theme: value?.theme, pageSize: value?.pageSize,
  };
  if (!isSettings(payload)) {
    return { ok: false, reason: "invalid-settings" };
  }
  try {
    // 编码与写入都放入异常边界;只持久化有限的普通字段。
    localStorage.setItem(SETTINGS_KEY, JSON.stringify(payload));
    return { ok: true };
  } catch (error) {
    return { ok: false, reason: error.name || "write-failed" };
  }
}

const saved = saveSettings({ theme: "dark", pageSize: 50 });
const restored = readSettings();
console.log(saved.ok, restored.reason, restored.value.theme);

在允许写入且期间没有其他页面改动该键的情况下,预期最后得到true、loaded、dark。这里提供的是推导出的结果判断,不是实测日志。写入失败时仍可在内存里应用用户所选偏好,但界面应说明“本次设置未持久化”,不要给出已保存的假反馈。

JSON只能保留相应的数据表示:Date通常变为字符串,方法和原型不会自动恢复,Map、Set也不会直接变为可用的原类型。对象中的undefined属性通常被省略,数组中的相应位置可能变为null;循环引用与默认处理的BigInt可使stringify抛错。示例因此只保存有限字符串和整数。

版本字段与受控配置恢复结构说明图
结构说明图:持久化记录包含版本与有限配置字段,恢复结果与默认值由应用约定;不表示所有对象类型都可无损保存。

回退路径:只重置自己的配置键

对于损坏或版本不支持的偏好,先使用默认值保证页面可读,再由明确的重置操作删除本应用的单个键。读取函数不自动覆写旧值,这样未知版本不会被旧页面悄悄销毁。若需要版本迁移,应识别旧结构后转换,最后再保存新版本。

function resetSettings() {
  try {
    // 只删除当前配置,不用clear清空同来源其他功能的数据。
    localStorage.removeItem(SETTINGS_KEY);
    return { ok: true, value: defaults() };
  } catch (error) {
    return { ok: false, reason: error.name || "reset-failed" };
  }
}

不要对整个来源直接调用clear作为默认修复,它可能连带删除其他功能的本地状态。重要业务数据需要独立可靠的保存方案,不能把重置偏好的操作套用到未备份的用户草稿。

结果确认:类型、版本与失败原因分别记录

排查顺序是先看读取值是否为null,再看文本是否合法JSON,随后看版本与字段是否可接受,最后确认是否发生访问或写入异常。对外提示区分“首次使用默认值”“配置无法恢复”“保存失败”,诊断记录只保存原因码,不打印完整用户数据。

localStorage操作是同步的,较大对象的编码和写入可能阻塞页面,因此适合少量配置,不应每次输入都同步存整份大型文档。多个标签页对同一个键读改写也不构成完整事务,不能把一次setItem等同于多步骤更新具备并发保护。

解析后修改对象会自动保存吗?

不会。修改的是内存对象,仍需重新编码并调用setItem。

存入JSON的null与键不存在一样吗?

不同。键不存在时getItem直接返回null;保存文本null时,先读到字符串,再经JSON.parse得到JavaScript null,结构检查应单独处理。

JSON.stringify能加密数据吗?

不能,它只编码。不要把敏感凭据当作普通偏好存入此示例,当前来源可执行的脚本可以访问相应存储。

维护方参考:localStorage字符串与来源规则、JSON.stringify类型转换规则。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>