HTML data属性读取永远是字符串,不存在深拷贝;所谓“深拷贝”仅发生在解析为对象后,需用JSON.parse配合structuredClone等实现。

HTML data 属性本身是字符串,不存在“深拷贝读取”这回事——你读到的永远是原始字符串,所谓“深拷贝”只发生在你把它解析成对象/数组之后。
为什么 dataset 或 getAttribute 读不出对象?
dataset 和 getAttribute() 返回的都是字符串,哪怕你在 HTML 里写了 data-config='{"theme":"dark","count":5}',JS 拿到的也只是 "{\"theme\":\"dark\",\"count\":5}" 这个字符串。浏览器不会自动 JSON.parse,也不会递归克隆。
- 直接访问
el.dataset.config或el.getAttribute("data-config")→ 得到字符串,不是对象 - 误以为
JSON.parse(el.dataset.config)就是“深拷贝” → 错,这只是解析,不是拷贝;如果原对象被修改,这个解析结果不受影响,但你后续对它的修改也和原字符串无关 - 想“拷贝 data 属性值再改” → 其实你是在拷贝解析后的 JS 对象,和 data 属性本身无直接关系
真正需要深拷贝的场景:解析后操作对象
当你用 JSON.parse() 把 data 属性值转成对象后,才可能涉及深拷贝需求——比如避免污染原始配置、或在组件内安全修改副本。
- 简单对象可用展开语法:
const configCopy = {...JSON.parse(el.getAttribute("data-config"))}(仅一层) - 嵌套对象必须用深拷贝:
JSON.parse(JSON.stringify(config))(注意 Date、Function、undefined 会丢失) - 更健壮的写法(推荐):
structuredClone(JSON.parse(el.getAttribute("data-config")))(Chrome 98+ / Firefox 94+ 支持) - 兼容旧环境:用 Lodash 的
_.cloneDeep()或手写递归函数
容易踩的坑:把“解析”当成“拷贝”,或混淆 DOM 同步
很多人写 const data = el.dataset; const copy = {...data},结果发现 copy 是空对象——因为 dataset 是 DOMStringMap,不是普通对象,... 展开无效。
立即学习“前端免费学习笔记(深入)”;
- 别对
dataset或el.attributes直接展开或Object.assign,它们不支持标准枚举 - 批量读取所有 data 属性并深拷贝?先用
Array.from(el.attributes).filter(a => a.name.startsWith("data-"))提取键值对,再逐个JSON.parse+ 深拷贝 - 写回 DOM 时,深拷贝后的对象还得手动
JSON.stringify回字符串,再setAttribute("data-config", str)
最常被忽略的一点:data 属性只是字符串容器,它不参与 JS 引用体系。所谓“深拷贝读取”,本质是你在字符串 → 解析 → 拷贝对象这条链路上选哪一环做拷贝——而第一步读取本身,永远是浅的、确定的、不可变的字符串。



















