JSON.stringify去重本质是序列化→Set去重→解析,但存在三大缺陷:属性顺序敏感、丢失函数/undefined/Symbol/循环引用、无法处理Date/RegExp/BigInt等特殊类型;推荐按字段用Map或深比较库替代。

用 JSON.stringify 对对象数组去重,本质是把每个对象转成字符串,再借助 Set 去重,最后还原。方法简单但有明显缺陷,不适用于多数真实场景。
怎么实现(基础写法)
核心思路:将对象序列化为唯一字符串 → 去重 → 反序列化回对象。
示例代码:
const arr = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice' }, // 重复项
];
const unique = [...new Set(arr.map(item => JSON.stringify(item)))]
.map(str => JSON.parse(str));
console.log(unique);
// [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
关键缺陷一:属性顺序敏感
JSON.stringify 对属性顺序有强依赖。相同内容、不同顺序的对象会被视为不同字符串。
-
{a: 1, b: 2}→"{"a":1,"b":2}" -
{b: 2, a: 1}→"{"b":2,"a":1}" - 两者字符串不同,Set 不会去重,结果保留“伪重复”
关键缺陷二:忽略函数、undefined、Symbol 和循环引用
JSON.stringify 会静默丢弃以下内容:
- 值为
undefined或function的属性(直接跳过) - 键为
Symbol的属性(完全不可见) - 循环引用对象(抛出
TypeError)
例如:{ id: 1, name: 'Alice', fn: () => {}, meta: undefined } 序列化后变成 {"id":1,"name":"Alice"},丢失信息导致误判“相同”。
关键缺陷三:无法处理 Date、RegExp、BigInt 等特殊类型
这些类型会被转换或丢失:
-
new Date()→ 字符串形式(如"2023-01-01T00:00:00.000Z"),但精度可能丢失 -
/abc/g→{}(空对象) -
1n(BigInt)→ 抛错TypeError: Do not know how to serialize a BigInt
一旦数组中含这类值,去重逻辑就可能崩溃或结果错乱。
替代建议(轻量且可靠)
若只需按某几个字段(如 id)去重,推荐用 Map 或 reduce:
// 按 id 去重(稳定、高效、无副作用) const uniqueById = Array.from( arr.reduce((map, item) => map.set(item.id, item), new Map()).values() );
若需全字段深度比较,应使用专门的深比较库(如 Lodash 的 uniqWith(eq)),或手写浅层/深层比较逻辑,避免依赖字符串序列化。


















