JSON.stringify()是唯一能保结构的序列化方式,必须用于data-*属性写入,读取时须用JSON.parse()配合try/catch和默认值兜底,否则会因字符串化或解析失败导致数据损坏。

不能直接存,必须用 JSON.stringify() 序列化后再写入,读取时再用 JSON.parse() 解析——否则你拿到的只是字符串或 "[object Object]"。
data-* 属性值永远是字符串,对象会被 toString() 毁掉
哪怕你写 el.dataset.config = { theme: "dark" },浏览器也会调用 toString(),最终存进去的是 "[object Object]"。这不是 bug,是规范行为:所有 dataset 赋值都会强制转字符串。
- 常见错误现象:
console.log(el.dataset.config)输出"[object Object]";JSON.parse(el.dataset.config)报错SyntaxError: Unexpected token o - 别试图用
join()、String()或手拼字符串替代JSON.stringify()——它们无法处理嵌套、null、布尔值或转义引号 -
JSON.stringify()是唯一能保结构的序列化方式(在 JSON 支持范围内)
写入时:setAttribute() 比 dataset 更可控
dataset 是只读代理,底层仍靠 setAttribute() 更新 DOM。直接用 setAttribute() 可避免驼峰转换干扰,也方便统一处理引号和转义。
- 正确写法:
el.setAttribute("data-config", JSON.stringify({ tabs: ["home", "profile"], active: true })) - 错误写法:
el.dataset.config = JSON.stringify(...)看似可行,但某些旧版 Safari 会静默失败 - 注意单双引号:HTML 属性值用双引号包裹,所以 JSON 内部必须用双引号——
JSON.stringify()默认满足,别手动替换成单引号
读取时:必须 try/catch,且要处理 undefined
dataset.xxx 拿不到属性时返回 undefined,不是空字符串或 null。直接传给 JSON.parse() 会炸。
立即学习“前端免费学习笔记(深入)”;
- 安全读取模式:
const config = JSON.parse(el.getAttribute("data-config") || "{}") - 更健壮写法:
try { const data = JSON.parse(el.getAttribute("data-config") || "null"); if (data !== null) { /* 使用 data */ } } catch (e) { /* 处理解析失败 */ } - 不要依赖
el.dataset.config读取 JSON——它自动做驼峰转换,但若 HTML 里写的是data-config-json,JS 里得用dataset.configJson,容易拼错
哪些数据不能 JSON.stringify()?提前检查再存
JSON.stringify() 会静默丢弃不可序列化字段,比如 undefined、function、Symbol、Date 对象(转成字符串)、RegExp,不会报错也不会警告。
- 典型翻车点:
{ createdAt: new Date(), handler: () => {} }存进去后变成{"createdAt":"2026-09-21T07:41:00.000Z"},handler消失无踪 - 建议存之前校验:
if (typeof obj === "object" && obj !== null && !Array.isArray(obj)) { /* 过滤掉函数/undefined 字段 */ } - 敏感数据(如 token、用户 ID)别塞进
data-——它不加密、不防 XSS,后续若拼进innerHTML就等于裸奔
真正麻烦的不是怎么存,而是忘记“每次读都要 parse + try/catch + 默认值兜底”——DOM 属性没有类型系统,所有结构化意图都靠开发者手动维护。



















