Map 不能直接 JSON.stringify 序列化,因其键可能为函数、对象、Symbol 等非 JSON 类型,且内部键值对不暴露为可枚举属性;正确做法是用 Array.from(map) 转为二维数组再序列化,读取时 new Map(JSON.parse(raw)) 还原。

Map 对象本身不能直接被 JSON.stringify 序列化,因为它的键可能是函数、对象、Symbol 等非 JSON 可序列化类型,且 Map 的结构不满足 JSON 标准格式。要实现“用 Map 配合 JSON 序列化做持久化缓存”,核心是**先将 Map 转为可序列化的普通对象或数组,存入 localStorage/sessionStorage;读取时再还原为 Map**。
为什么不能直接 JSON.stringify(map)?
Map 是迭代器对象,JSON.stringify(new Map([['a', 1]])) 会返回空对象 {} —— 因为 JSON 只能处理 plain object 和 array,且只遍历自身可枚举属性,而 Map 的键值对存在内部槽位,不暴露为属性。
正确序列化:转成键值对数组
利用 Map 的 Array.from(map) 或展开语法 [...map],将其转为二维数组(如 [["key1", 1], ["key2", "val"]]),这种结构完全兼容 JSON:
✅ 推荐写法(安全、通用):
// 保存
const cache = new Map();
cache.set('token', 'abc123');
cache.set('user', { id: 1, name: 'Alice' });
// 序列化:转为数组
const serialized = JSON.stringify(Array.from(cache));
localStorage.setItem('app-cache', serialized);
// 还原:从数组构造新 Map
const raw = localStorage.getItem('app-cache');
const restored = raw ? new Map(JSON.parse(raw)) : new Map();
支持复杂 key 的注意事项
如果 Map 的 key 是对象或函数,JSON.stringify 会丢失信息(对象 key 变成 "{}",函数变 null)。持久化缓存应避免这类 key:
- 只用字符串、数字、布尔值作为 key(最稳妥)
- 若必须用对象 key,需提前转换为唯一字符串(如用
JSON.stringify(obj)或生成 hash) - Symbol / 函数 key 无法持久化,应主动过滤或报错提示
封装一个简易持久化 Map 类
可封装成带自动同步能力的工具类,提升复用性:
class PersistentMap extends Map {
constructor(key, storage = localStorage) {
const saved = storage.getItem(key);
super(saved ? JSON.parse(saved) : []);
this.key = key;
this.storage = storage;
}
set(k, v) {
super.set(k, v);
this.persist();
return this;
}
delete(k) {
const result = super.delete(k);
if (result) this.persist();
return result;
}
clear() {
super.clear();
this.persist();
}
persist() {
this.storage.setItem(this.key, JSON.stringify(Array.from(this)));
}
}
// 使用
const cache = new PersistentMap('my-app-cache');
cache.set('theme', 'dark');
cache.set('count', 42);
// 关闭页面再打开,数据仍在











